target: Use proper data types for timer callback
[openocd.git] / src / target / target.c
index 31ade6acff60d9908b22734f3ed9092e325a1a17..a3230d2486fbccac84221cd2f6383669b9625400 100644 (file)
  *   Copyright (C) 2008 by Rick Altherr                                    *
  *   kc8apf@kc8apf.net>                                                    *
  *                                                                         *
+ *   Copyright (C) 2011 by Broadcom Corporation                            *
+ *   Evan Hunter - ehunter@broadcom.com                                    *
+ *                                                                         *
+ *   Copyright (C) ST-Ericsson SA 2011                                     *
+ *   michel.jaouen@stericsson.com : smp minimum support                    *
+ *                                                                         *
+ *   Copyright (C) 2011 Andreas Fritiofson                                 *
+ *   andreas.fritiofson@gmail.com                                          *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
  *   GNU General Public License for more details.                          *
  *                                                                         *
  *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 #include "register.h"
 #include "trace.h"
 #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, target_addr_t address,
+               uint32_t count, uint8_t *buffer);
+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);
+               int argc, Jim_Obj * const *argv);
 static int target_mem2array(Jim_Interp *interp, struct target *target,
-               int argc, Jim_Obj *const *argv);
+               int argc, Jim_Obj * const *argv);
 static int target_register_user_commands(struct command_context *cmd_ctx);
+static int target_get_gdb_fileio_info_default(struct target *target,
+               struct gdb_fileio_info *fileio_info);
+static int target_gdb_fileio_end_default(struct target *target, int retcode,
+               int fileio_errno, bool ctrl_c);
+static int target_profiling_default(struct target *target, uint32_t *samples,
+               uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds);
 
 /* targets */
 extern struct target_type arm7tdmi_target;
@@ -64,17 +87,31 @@ extern struct target_type fa526_target;
 extern struct target_type feroceon_target;
 extern struct target_type dragonite_target;
 extern struct target_type xscale_target;
-extern struct target_type cortexm3_target;
-extern struct target_type cortexa8_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;
 extern struct target_type mips_m4k_target;
 extern struct target_type avr_target;
 extern struct target_type dsp563xx_target;
+extern struct target_type dsp5680xx_target;
 extern struct target_type testee_target;
 extern struct target_type avr32_ap7k_target;
-
-static struct target_type *target_types[] =
-{
+extern struct target_type hla_target;
+extern struct target_type nds32_v2_target;
+extern struct target_type nds32_v3_target;
+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,
        &arm9tdmi_target,
        &arm920t_target,
@@ -86,20 +123,39 @@ static struct target_type *target_types[] =
        &feroceon_target,
        &dragonite_target,
        &xscale_target,
-       &cortexm3_target,
-       &cortexa8_target,
+       &cortexm_target,
+       &cortexa_target,
+       &cortexr4_target,
        &arm11_target,
+       &ls1_sap_target,
        &mips_m4k_target,
        &avr_target,
        &dsp563xx_target,
+       &dsp5680xx_target,
        &testee_target,
        &avr32_ap7k_target,
+       &hla_target,
+       &nds32_v2_target,
+       &nds32_v3_target,
+       &nds32_v3m_target,
+       &or1k_target,
+       &quark_x10xx_target,
+       &quark_d20xx_target,
+       &stm8_target,
+       &riscv_target,
+       &mem_ap_target,
+       &esirisc_target,
+#if BUILD_TARGET64
+       &aarch64_target,
+#endif
        NULL,
 };
 
-struct target *all_targets = NULL;
-static struct target_event_callback *target_event_callbacks = NULL;
-static struct target_timer_callback *target_timer_callbacks = NULL;
+struct target *all_targets;
+static struct target_event_callback *target_event_callbacks;
+static struct target_timer_callback *target_timer_callbacks;
+LIST_HEAD(target_reset_callback_list);
+LIST_HEAD(target_trace_callback_list);
 static const int polling_interval = 100;
 
 static const Jim_Nvp nvp_assert[] = {
@@ -132,16 +188,13 @@ static const char *target_strerror_safe(int err)
        const Jim_Nvp *n;
 
        n = Jim_Nvp_value2name_simple(nvp_error_target, err);
-       if (n->name == NULL) {
+       if (n->name == NULL)
                return "unknown";
-       } else {
+       else
                return n->name;
-       }
 }
 
 static const Jim_Nvp nvp_target_event[] = {
-       { .value = TARGET_EVENT_OLD_gdb_program_config , .name = "old-gdb_program_config" },
-       { .value = TARGET_EVENT_OLD_pre_resume         , .name = "old-pre_resume" },
 
        { .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" },
        { .value = TARGET_EVENT_HALTED, .name = "halted" },
@@ -152,19 +205,12 @@ static const Jim_Nvp nvp_target_event[] = {
        { .name = "gdb-start", .value = TARGET_EVENT_GDB_START },
        { .name = "gdb-end", .value = TARGET_EVENT_GDB_END },
 
-       /* historical name */
-
-       { .value = TARGET_EVENT_RESET_START, .name = "reset-start" },
-
+       { .value = TARGET_EVENT_RESET_START,         .name = "reset-start" },
        { .value = TARGET_EVENT_RESET_ASSERT_PRE,    .name = "reset-assert-pre" },
        { .value = TARGET_EVENT_RESET_ASSERT,        .name = "reset-assert" },
        { .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" },
 
@@ -183,9 +229,7 @@ static const Jim_Nvp nvp_target_event[] = {
        { .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" },
        { .value = TARGET_EVENT_GDB_FLASH_ERASE_END  , .name = "gdb-flash-erase-end" },
 
-       { .value = TARGET_EVENT_RESUME_START, .name = "resume-start" },
-       { .value = TARGET_EVENT_RESUMED     , .name = "resume-ok" },
-       { .value = TARGET_EVENT_RESUME_END  , .name = "resume-end" },
+       { .value = TARGET_EVENT_TRACE_CONFIG, .name = "trace-config" },
 
        { .name = NULL, .value = -1 }
 };
@@ -199,13 +243,14 @@ static const Jim_Nvp nvp_target_state[] = {
        { .name = NULL, .value = -1 },
 };
 
-static const Jim_Nvp nvp_target_debug_reason [] = {
+static const Jim_Nvp nvp_target_debug_reason[] = {
        { .name = "debug-request"            , .value = DBG_REASON_DBGRQ },
        { .name = "breakpoint"               , .value = DBG_REASON_BREAKPOINT },
        { .name = "watchpoint"               , .value = DBG_REASON_WATCHPOINT },
        { .name = "watchpoint-and-breakpoint", .value = DBG_REASON_WPTANDBKPT },
        { .name = "single-step"              , .value = DBG_REASON_SINGLESTEP },
        { .name = "target-not-halted"        , .value = DBG_REASON_NOTHALTED  },
+       { .name = "program-exit"             , .value = DBG_REASON_EXIT },
        { .name = "undefined"                , .value = DBG_REASON_UNDEFINED },
        { .name = NULL, .value = -1 },
 };
@@ -239,15 +284,40 @@ const char *debug_reason_name(struct target *t)
        return cp;
 }
 
-const char *
-target_state_name( struct target *t )
+const char *target_state_name(struct target *t)
 {
        const char *cp;
        cp = Jim_Nvp_value2name_simple(nvp_target_state, t->state)->name;
-       if( !cp ){
+       if (!cp) {
                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;
+}
+
+const char *target_event_name(enum target_event event)
+{
+       const char *cp;
+       cp = Jim_Nvp_value2name_simple(nvp_target_event, event)->name;
+       if (!cp) {
+               LOG_ERROR("Invalid target event: %d", (int)(event));
+               cp = "(*BUG*unknown*BUG*)";
+       }
+       return cp;
+}
+
+const char *target_reset_mode_name(enum target_reset_mode reset_mode)
+{
+       const char *cp;
+       cp = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name;
+       if (!cp) {
+               LOG_ERROR("Invalid target reset mode: %d", (int)(reset_mode));
+               cp = "(*BUG*unknown*BUG*)";
+       }
        return cp;
 }
 
@@ -261,14 +331,22 @@ static int new_target_number(void)
        x = -1;
        t = all_targets;
        while (t) {
-               if (x < t->target_number) {
+               if (x < t->target_number)
                        x = t->target_number;
-               }
                t = t->next;
        }
        return x + 1;
 }
 
+/* read a uint64_t from a buffer in target memory endianness */
+uint64_t target_buffer_get_u64(struct target *target, const uint8_t *buffer)
+{
+       if (target->endianness == TARGET_LITTLE_ENDIAN)
+               return le_to_h_u64(buffer);
+       else
+               return be_to_h_u64(buffer);
+}
+
 /* read a uint32_t from a buffer in target memory endianness */
 uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer)
 {
@@ -278,6 +356,15 @@ uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer)
                return be_to_h_u32(buffer);
 }
 
+/* read a uint24_t from a buffer in target memory endianness */
+uint32_t target_buffer_get_u24(struct target *target, const uint8_t *buffer)
+{
+       if (target->endianness == TARGET_LITTLE_ENDIAN)
+               return le_to_h_u24(buffer);
+       else
+               return be_to_h_u24(buffer);
+}
+
 /* read a uint16_t from a buffer in target memory endianness */
 uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer)
 {
@@ -293,6 +380,15 @@ static uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer
        return *buffer & 0x0ff;
 }
 
+/* write a uint64_t to a buffer in target memory endianness */
+void target_buffer_set_u64(struct target *target, uint8_t *buffer, uint64_t value)
+{
+       if (target->endianness == TARGET_LITTLE_ENDIAN)
+               h_u64_to_le(buffer, value);
+       else
+               h_u64_to_be(buffer, value);
+}
+
 /* write a uint32_t to a buffer in target memory endianness */
 void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value)
 {
@@ -302,6 +398,15 @@ void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t valu
                h_u32_to_be(buffer, value);
 }
 
+/* write a uint24_t to a buffer in target memory endianness */
+void target_buffer_set_u24(struct target *target, uint8_t *buffer, uint32_t value)
+{
+       if (target->endianness == TARGET_LITTLE_ENDIAN)
+               h_u24_to_le(buffer, value);
+       else
+               h_u24_to_be(buffer, value);
+}
+
 /* write a uint16_t to a buffer in target memory endianness */
 void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t value)
 {
@@ -317,6 +422,54 @@ static void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t
        *buffer = value;
 }
 
+/* write a uint64_t array to a buffer in target memory endianness */
+void target_buffer_get_u64_array(struct target *target, const uint8_t *buffer, uint32_t count, uint64_t *dstbuf)
+{
+       uint32_t i;
+       for (i = 0; i < count; i++)
+               dstbuf[i] = target_buffer_get_u64(target, &buffer[i * 8]);
+}
+
+/* write a uint32_t array to a buffer in target memory endianness */
+void target_buffer_get_u32_array(struct target *target, const uint8_t *buffer, uint32_t count, uint32_t *dstbuf)
+{
+       uint32_t i;
+       for (i = 0; i < count; i++)
+               dstbuf[i] = target_buffer_get_u32(target, &buffer[i * 4]);
+}
+
+/* write a uint16_t array to a buffer in target memory endianness */
+void target_buffer_get_u16_array(struct target *target, const uint8_t *buffer, uint32_t count, uint16_t *dstbuf)
+{
+       uint32_t i;
+       for (i = 0; i < count; i++)
+               dstbuf[i] = target_buffer_get_u16(target, &buffer[i * 2]);
+}
+
+/* write a uint64_t array to a buffer in target memory endianness */
+void target_buffer_set_u64_array(struct target *target, uint8_t *buffer, uint32_t count, const uint64_t *srcbuf)
+{
+       uint32_t i;
+       for (i = 0; i < count; i++)
+               target_buffer_set_u64(target, &buffer[i * 8], srcbuf[i]);
+}
+
+/* write a uint32_t array to a buffer in target memory endianness */
+void target_buffer_set_u32_array(struct target *target, uint8_t *buffer, uint32_t count, const uint32_t *srcbuf)
+{
+       uint32_t i;
+       for (i = 0; i < count; i++)
+               target_buffer_set_u32(target, &buffer[i * 4], srcbuf[i]);
+}
+
+/* write a uint16_t array to a buffer in target memory endianness */
+void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_t count, const uint16_t *srcbuf)
+{
+       uint32_t i;
+       for (i = 0; i < count; i++)
+               target_buffer_set_u16(target, &buffer[i * 2], srcbuf[i]);
+}
+
 /* return a pointer to a configured target; id is name or number */
 struct target *get_target(const char *id)
 {
@@ -324,9 +477,9 @@ struct target *get_target(const char *id)
 
        /* try as tcltarget name */
        for (target = all_targets; target; target = target->next) {
-               if (target->cmd_name == NULL)
+               if (target_name(target) == NULL)
                        continue;
-               if (strcmp(id, target->cmd_name) == 0)
+               if (strcmp(id, target_name(target)) == 0)
                        return target;
        }
 
@@ -340,7 +493,7 @@ struct target *get_target(const char *id)
        for (target = all_targets; target; target = target->next) {
                if (target->target_number == (int)num) {
                        LOG_WARNING("use '%s' as target identifier, not '%u'",
-                                       target->cmd_name, num);
+                                       target_name(target), num);
                        return target;
                }
        }
@@ -349,26 +502,24 @@ struct target *get_target(const char *id)
 }
 
 /* returns a pointer to the n-th configured target */
-static struct target *get_target_by_num(int num)
+struct target *get_target_by_num(int num)
 {
        struct target *target = all_targets;
 
        while (target) {
-               if (target->target_number == num) {
+               if (target->target_number == num)
                        return target;
-               }
                target = target->next;
        }
 
        return NULL;
 }
 
-struct targetget_current_target(struct command_context *cmd_ctx)
+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)
-       {
+       if (target == NULL) {
                LOG_ERROR("BUG: current_target out of bounds");
                exit(-1);
        }
@@ -376,13 +527,19 @@ 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;
 
        /* We can't poll until after examine */
-       if (!target_was_examined(target))
-       {
+       if (!target_was_examined(target)) {
                /* Fail silently lest we pollute the log */
                return ERROR_FAIL;
        }
@@ -391,16 +548,12 @@ int target_poll(struct target *target)
        if (retval != ERROR_OK)
                return retval;
 
-       if (target->halt_issued)
-       {
+       if (target->halt_issued) {
                if (target->state == TARGET_HALTED)
-               {
                        target->halt_issued = false;
-               } else
-               {
-                       long long t = timeval_ms() - target->halt_issued_time;
-                       if (t>1000)
-                       {
+               else {
+                       int64_t t = timeval_ms() - target->halt_issued_time;
+                       if (t > DEFAULT_HALT_TIMEOUT) {
                                target->halt_issued = false;
                                LOG_INFO("Halt timed out, wake up GDB.");
                                target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
@@ -415,8 +568,7 @@ int target_halt(struct target *target)
 {
        int retval;
        /* We can't poll until after examine */
-       if (!target_was_examined(target))
-       {
+       if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
@@ -461,24 +613,29 @@ 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;
 
        /* We can't poll until after examine */
-       if (!target_was_examined(target))
-       {
+       if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
 
+       target_call_event_callbacks(target, TARGET_EVENT_RESUME_START);
+
        /* note that resume *must* be asynchronous. The CPU can halt before
         * we poll. The CPU can even halt at the current PC as a result of
         * a software breakpoint being inserted by (a bug?) the application.
         */
-       if ((retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution)) != ERROR_OK)
+       retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution);
+       if (retval != ERROR_OK)
                return retval;
 
+       target_call_event_callbacks(target, TARGET_EVENT_RESUME_END);
+
        return retval;
 }
 
@@ -493,6 +650,10 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res
                return ERROR_FAIL;
        }
 
+       struct target *target;
+       for (target = all_targets; target; target = target->next)
+               target_call_reset_callbacks(target, reset_mode);
+
        /* disable polling during reset to make reset event scripts
         * more predictable, i.e. dr/irscan & pathmove in events will
         * not have JTAG operations injected into the middle of a sequence.
@@ -508,23 +669,23 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res
 
        if (retval != JIM_OK) {
                Jim_MakeErrorMessage(cmd_ctx->interp);
-               command_print(NULL,"%s\n", Jim_GetString(Jim_GetResult(cmd_ctx->interp), NULL));
+               command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(cmd_ctx->interp), NULL));
                return ERROR_FAIL;
        }
 
        /* We want any events to be processed before the prompt */
        retval = target_call_timer_callbacks_now();
 
-       struct target *target;
        for (target = all_targets; target; target = target->next) {
                target->type->check_reset(target);
+               target->running_alg = false;
        }
 
        return retval;
 }
 
 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;
@@ -550,7 +711,15 @@ static int default_check_reset(struct target *target)
 
 int target_examine_one(struct target *target)
 {
-       return target->type->examine(target);
+       target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START);
+
+       int retval = target->type->examine(target);
+       if (retval != ERROR_OK)
+               return retval;
+
+       target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END);
+
+       return ERROR_OK;
 }
 
 static int jtag_enable_callback(enum jtag_event event, void *priv)
@@ -561,10 +730,10 @@ static int jtag_enable_callback(enum jtag_event event, void *priv)
                return ERROR_OK;
 
        jtag_unregister_event_callback(jtag_enable_callback, target);
+
        return target_examine_one(target);
 }
 
-
 /* Targets that correctly implement init + examine, i.e.
  * no communication with target during init:
  *
@@ -575,57 +744,41 @@ int target_examine(void)
        int retval = ERROR_OK;
        struct target *target;
 
-       for (target = all_targets; target; target = target->next)
-       {
+       for (target = all_targets; target; target = target->next) {
                /* defer examination, but don't skip it */
                if (!target->tap->enabled) {
                        jtag_register_event_callback(jtag_enable_callback,
                                        target);
                        continue;
                }
-               if ((retval = target_examine_one(target)) != ERROR_OK)
+
+               if (target->defer_examine)
+                       continue;
+
+               retval = target_examine_one(target);
+               if (retval != ERROR_OK)
                        return retval;
        }
        return retval;
 }
+
 const char *target_type_name(struct target *target)
 {
        return target->type->name;
 }
 
-static int target_write_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
-{
-       if (!target_was_examined(target))
-       {
-               LOG_ERROR("Target not examined yet");
-               return ERROR_FAIL;
-       }
-       return target->type->write_memory_imp(target, address, size, count, buffer);
-}
-
-static int target_read_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
-{
-       if (!target_was_examined(target))
-       {
-               LOG_ERROR("Target not examined yet");
-               return ERROR_FAIL;
-       }
-       return target->type->read_memory_imp(target, address, size, count, buffer);
-}
-
-static int target_soft_reset_halt_imp(struct target *target)
+static int target_soft_reset_halt(struct target *target)
 {
-       if (!target_was_examined(target))
-       {
+       if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
-       if (!target->type->soft_reset_halt_imp) {
+       if (!target->type->soft_reset_halt) {
                LOG_ERROR("Target %s does not support soft_reset_halt",
                                target_name(target));
                return ERROR_FAIL;
        }
-       return target->type->soft_reset_halt_imp(target);
+       return target->type->soft_reset_halt(target);
 }
 
 /**
@@ -647,8 +800,7 @@ int target_run_algorithm(struct target *target,
 {
        int retval = ERROR_FAIL;
 
-       if (!target_was_examined(target))
-       {
+       if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                goto done;
        }
@@ -669,182 +821,520 @@ done:
        return retval;
 }
 
-
-int target_read_memory(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+/**
+ * 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.
+ */
+int target_start_algorithm(struct target *target,
+               int num_mem_params, struct mem_param *mem_params,
+               int num_reg_params, struct reg_param *reg_params,
+               uint32_t entry_point, uint32_t exit_point,
+               void *arch_info)
 {
-       return target->type->read_memory(target, address, size, count, buffer);
-}
+       int retval = ERROR_FAIL;
 
-static int target_read_phys_memory(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
-{
-       return target->type->read_phys_memory(target, address, size, count, buffer);
-}
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               goto done;
+       }
+       if (!target->type->start_algorithm) {
+               LOG_ERROR("Target type '%s' does not support %s",
+                               target_type_name(target), __func__);
+               goto done;
+       }
+       if (target->running_alg) {
+               LOG_ERROR("Target is already running an algorithm");
+               goto done;
+       }
 
-int target_write_memory(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
-{
-       return target->type->write_memory(target, address, size, count, buffer);
-}
+       target->running_alg = true;
+       retval = target->type->start_algorithm(target,
+                       num_mem_params, mem_params,
+                       num_reg_params, reg_params,
+                       entry_point, exit_point, arch_info);
 
-static int target_write_phys_memory(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
-{
-       return target->type->write_phys_memory(target, address, size, count, buffer);
+done:
+       return retval;
 }
 
-int target_bulk_write_memory(struct target *target,
-               uint32_t address, uint32_t count, uint8_t *buffer)
+/**
+ * Waits for an algorithm started with target_start_algorithm() to complete.
+ *
+ * @param target used to run the algorithm
+ * @param arch_info target-specific description of the algorithm.
+ */
+int target_wait_algorithm(struct target *target,
+               int num_mem_params, struct mem_param *mem_params,
+               int num_reg_params, struct reg_param *reg_params,
+               uint32_t exit_point, int timeout_ms,
+               void *arch_info)
 {
-       return target->type->bulk_write_memory(target, address, count, buffer);
-}
+       int retval = ERROR_FAIL;
 
-int target_add_breakpoint(struct target *target,
-               struct breakpoint *breakpoint)
-{
-       if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target->cmd_name);
-               return ERROR_TARGET_NOT_HALTED;
+       if (!target->type->wait_algorithm) {
+               LOG_ERROR("Target type '%s' does not support %s",
+                               target_type_name(target), __func__);
+               goto done;
        }
-       return target->type->add_breakpoint(target, breakpoint);
-}
-int target_remove_breakpoint(struct target *target,
-               struct breakpoint *breakpoint)
-{
-       return target->type->remove_breakpoint(target, breakpoint);
-}
-
-int target_add_watchpoint(struct target *target,
-               struct watchpoint *watchpoint)
-{
-       if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target->cmd_name);
-               return ERROR_TARGET_NOT_HALTED;
+       if (!target->running_alg) {
+               LOG_ERROR("Target is not running an algorithm");
+               goto done;
        }
-       return target->type->add_watchpoint(target, watchpoint);
-}
-int target_remove_watchpoint(struct target *target,
-               struct watchpoint *watchpoint)
-{
-       return target->type->remove_watchpoint(target, watchpoint);
-}
 
-int target_get_gdb_reg_list(struct target *target,
-               struct reg **reg_list[], int *reg_list_size)
-{
-       return target->type->get_gdb_reg_list(target, reg_list, reg_list_size);
-}
-int target_step(struct target *target,
-               int current, uint32_t address, int handle_breakpoints)
-{
-       return target->type->step(target, current, address, handle_breakpoints);
-}
+       retval = target->type->wait_algorithm(target,
+                       num_mem_params, mem_params,
+                       num_reg_params, reg_params,
+                       exit_point, timeout_ms, arch_info);
+       if (retval != ERROR_TARGET_TIMEOUT)
+               target->running_alg = false;
 
+done:
+       return retval;
+}
 
 /**
- * Reset the @c examined flag for the given target.
- * Pure paranoia -- targets are zeroed on allocation.
+ * 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
  */
-static void target_reset_examined(struct target *target)
-{
-       target->examined = false;
-}
-
-static int
-err_read_phys_memory(struct target *target, uint32_t address,
-               uint32_t size, uint32_t count, uint8_t *buffer)
-{
-       LOG_ERROR("Not implemented: %s", __func__);
-       return ERROR_FAIL;
-}
 
-static int
-err_write_phys_memory(struct target *target, uint32_t address,
-               uint32_t size, uint32_t count, uint8_t *buffer)
+int target_run_flash_async_algorithm(struct target *target,
+               const uint8_t *buffer, uint32_t count, int block_size,
+               int num_mem_params, struct mem_param *mem_params,
+               int num_reg_params, struct reg_param *reg_params,
+               uint32_t buffer_start, uint32_t buffer_size,
+               uint32_t entry_point, uint32_t exit_point, void *arch_info)
 {
-       LOG_ERROR("Not implemented: %s", __func__);
-       return ERROR_FAIL;
-}
+       int retval;
+       int timeout = 0;
 
-static int handle_target(void *priv);
+       const uint8_t *buffer_orig = buffer;
 
-static int target_init_one(struct command_context *cmd_ctx,
-               struct target *target)
-{
-       target_reset_examined(target);
+       /* Set up working area. First word is write pointer, second word is read pointer,
+        * rest is fifo data area. */
+       uint32_t wp_addr = buffer_start;
+       uint32_t rp_addr = buffer_start + 4;
+       uint32_t fifo_start_addr = buffer_start + 8;
+       uint32_t fifo_end_addr = buffer_start + buffer_size;
 
-       struct target_type *type = target->type;
-       if (type->examine == NULL)
-               type->examine = default_examine;
+       uint32_t wp = fifo_start_addr;
+       uint32_t rp = fifo_start_addr;
 
-       if (type->check_reset== NULL)
-               type->check_reset = default_check_reset;
+       /* validate block_size is 2^n */
+       assert(!block_size || !(block_size & (block_size - 1)));
 
-       int retval = type->init_target(cmd_ctx, target);
-       if (ERROR_OK != retval)
-       {
-               LOG_ERROR("target '%s' init failed", target_name(target));
+       retval = target_write_u32(target, wp_addr, wp);
+       if (retval != ERROR_OK)
+               return retval;
+       retval = target_write_u32(target, rp_addr, rp);
+       if (retval != ERROR_OK)
                return retval;
-       }
 
-       /**
-        * @todo get rid of those *memory_imp() methods, now that all
-        * callers are using target_*_memory() accessors ... and make
-        * sure the "physical" paths handle the same issues.
-        */
-       /* a non-invasive way(in terms of patches) to add some code that
-        * runs before the type->write/read_memory implementation
-        */
-       type->write_memory_imp = target->type->write_memory;
-       type->write_memory = target_write_memory_imp;
+       /* Start up algorithm on target and let it idle while writing the first chunk */
+       retval = target_start_algorithm(target, num_mem_params, mem_params,
+                       num_reg_params, reg_params,
+                       entry_point,
+                       exit_point,
+                       arch_info);
 
-       type->read_memory_imp = target->type->read_memory;
-       type->read_memory = target_read_memory_imp;
+       if (retval != ERROR_OK) {
+               LOG_ERROR("error starting target flash write algorithm");
+               return retval;
+       }
 
-       type->soft_reset_halt_imp = target->type->soft_reset_halt;
-       type->soft_reset_halt = target_soft_reset_halt_imp;
+       while (count > 0) {
+
+               retval = target_read_u32(target, rp_addr, &rp);
+               if (retval != ERROR_OK) {
+                       LOG_ERROR("failed to get read pointer");
+                       break;
+               }
+
+               LOG_DEBUG("offs 0x%zx count 0x%" PRIx32 " wp 0x%" PRIx32 " rp 0x%" PRIx32,
+                       (size_t) (buffer - buffer_orig), count, wp, rp);
+
+               if (rp == 0) {
+                       LOG_ERROR("flash write algorithm aborted by target");
+                       retval = ERROR_FLASH_OPERATION_FAILED;
+                       break;
+               }
+
+               if (((rp - fifo_start_addr) & (block_size - 1)) || rp < fifo_start_addr || rp >= fifo_end_addr) {
+                       LOG_ERROR("corrupted fifo read pointer 0x%" PRIx32, rp);
+                       break;
+               }
+
+               /* Count the number of bytes available in the fifo without
+                * crossing the wrap around. Make sure to not fill it completely,
+                * because that would make wp == rp and that's the empty condition. */
+               uint32_t thisrun_bytes;
+               if (rp > wp)
+                       thisrun_bytes = rp - wp - block_size;
+               else if (rp > fifo_start_addr)
+                       thisrun_bytes = fifo_end_addr - wp;
+               else
+                       thisrun_bytes = fifo_end_addr - wp - block_size;
+
+               if (thisrun_bytes == 0) {
+                       /* Throttle polling a bit if transfer is (much) faster than flash
+                        * programming. The exact delay shouldn't matter as long as it's
+                        * less than buffer size / flash speed. This is very unlikely to
+                        * run when using high latency connections such as USB. */
+                       alive_sleep(10);
+
+                       /* to stop an infinite loop on some targets check and increment a timeout
+                        * this issue was observed on a stellaris using the new ICDI interface */
+                       if (timeout++ >= 500) {
+                               LOG_ERROR("timeout waiting for algorithm, a target reset is recommended");
+                               return ERROR_FLASH_OPERATION_FAILED;
+                       }
+                       continue;
+               }
+
+               /* reset our timeout */
+               timeout = 0;
+
+               /* Limit to the amount of data we actually want to write */
+               if (thisrun_bytes > count * block_size)
+                       thisrun_bytes = count * block_size;
+
+               /* Write data to fifo */
+               retval = target_write_buffer(target, wp, thisrun_bytes, buffer);
+               if (retval != ERROR_OK)
+                       break;
+
+               /* Update counters and wrap write pointer */
+               buffer += thisrun_bytes;
+               count -= thisrun_bytes / block_size;
+               wp += thisrun_bytes;
+               if (wp >= fifo_end_addr)
+                       wp = fifo_start_addr;
+
+               /* Store updated write pointer to target */
+               retval = target_write_u32(target, wp_addr, wp);
+               if (retval != ERROR_OK)
+                       break;
+
+               /* Avoid GDB timeouts */
+               keep_alive();
+       }
+
+       if (retval != ERROR_OK) {
+               /* abort flash write algorithm on target */
+               target_write_u32(target, wp_addr, 0);
+       }
+
+       int retval2 = target_wait_algorithm(target, num_mem_params, mem_params,
+                       num_reg_params, reg_params,
+                       exit_point,
+                       10000,
+                       arch_info);
+
+       if (retval2 != ERROR_OK) {
+               LOG_ERROR("error waiting for target flash write algorithm");
+               retval = retval2;
+       }
+
+       if (retval == ERROR_OK) {
+               /* check if algorithm set rp = 0 after fifo writer loop finished */
+               retval = target_read_u32(target, rp_addr, &rp);
+               if (retval == ERROR_OK && rp == 0) {
+                       LOG_ERROR("flash write algorithm aborted by target");
+                       retval = ERROR_FLASH_OPERATION_FAILED;
+               }
+       }
+
+       return retval;
+}
+
+int target_read_memory(struct target *target,
+               target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+       if (!target->type->read_memory) {
+               LOG_ERROR("Target %s doesn't support read_memory", target_name(target));
+               return ERROR_FAIL;
+       }
+       return target->type->read_memory(target, address, size, count, buffer);
+}
+
+int target_read_phys_memory(struct target *target,
+               target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+       if (!target->type->read_phys_memory) {
+               LOG_ERROR("Target %s doesn't support read_phys_memory", target_name(target));
+               return ERROR_FAIL;
+       }
+       return target->type->read_phys_memory(target, address, size, count, buffer);
+}
+
+int target_write_memory(struct target *target,
+               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");
+               return ERROR_FAIL;
+       }
+       if (!target->type->write_memory) {
+               LOG_ERROR("Target %s doesn't support write_memory", target_name(target));
+               return ERROR_FAIL;
+       }
+       return target->type->write_memory(target, address, size, count, buffer);
+}
+
+int target_write_phys_memory(struct target *target,
+               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");
+               return ERROR_FAIL;
+       }
+       if (!target->type->write_phys_memory) {
+               LOG_ERROR("Target %s doesn't support write_phys_memory", target_name(target));
+               return ERROR_FAIL;
+       }
+       return target->type->write_phys_memory(target, address, size, count, buffer);
+}
+
+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 (add breakpoint)", target_name(target));
+               return ERROR_TARGET_NOT_HALTED;
+       }
+       return target->type->add_breakpoint(target, breakpoint);
+}
+
+int target_add_context_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
+{
+       if (target->state != TARGET_HALTED) {
+               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);
+}
+
+int target_add_hybrid_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
+{
+       if (target->state != TARGET_HALTED) {
+               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);
+}
+
+int target_remove_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
+{
+       return target->type->remove_breakpoint(target, breakpoint);
+}
+
+int target_add_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
+{
+       if (target->state != TARGET_HALTED) {
+               LOG_WARNING("target %s is not halted (add watchpoint)", target_name(target));
+               return ERROR_TARGET_NOT_HALTED;
+       }
+       return target->type->add_watchpoint(target, watchpoint);
+}
+int target_remove_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
+{
+       return target->type->remove_watchpoint(target, watchpoint);
+}
+int target_hit_watchpoint(struct target *target,
+               struct watchpoint **hit_watchpoint)
+{
+       if (target->state != TARGET_HALTED) {
+               LOG_WARNING("target %s is not halted (hit watchpoint)", target->cmd_name);
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (target->type->hit_watchpoint == NULL) {
+               /* For backward compatible, if hit_watchpoint is not implemented,
+                * return ERROR_FAIL such that gdb_server will not take the nonsense
+                * information. */
+               return ERROR_FAIL;
+       }
+
+       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, target_addr_t address, int handle_breakpoints)
+{
+       return target->type->step(target, current, address, handle_breakpoints);
+}
+
+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 (gdb fileio)", target->cmd_name);
+               return ERROR_TARGET_NOT_HALTED;
+       }
+       return target->type->get_gdb_fileio_info(target, fileio_info);
+}
+
+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 (gdb fileio end)", target->cmd_name);
+               return ERROR_TARGET_NOT_HALTED;
+       }
+       return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c);
+}
+
+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 (profiling)", target->cmd_name);
+               return ERROR_TARGET_NOT_HALTED;
+       }
+       return target->type->profiling(target, samples, max_num_samples,
+                       num_samples, seconds);
+}
+
+/**
+ * Reset the @c examined flag for the given target.
+ * Pure paranoia -- targets are zeroed on allocation.
+ */
+static void target_reset_examined(struct target *target)
+{
+       target->examined = false;
+}
+
+static int handle_target(void *priv);
+
+static int target_init_one(struct command_context *cmd_ctx,
+               struct target *target)
+{
+       target_reset_examined(target);
+
+       struct target_type *type = target->type;
+       if (type->examine == NULL)
+               type->examine = default_examine;
+
+       if (type->check_reset == NULL)
+               type->check_reset = default_check_reset;
+
+       assert(type->init_target != NULL);
+
+       int retval = type->init_target(cmd_ctx, target);
+       if (ERROR_OK != retval) {
+               LOG_ERROR("target '%s' init failed", target_name(target));
+               return retval;
+       }
 
        /* Sanity-check MMU support ... stub in what we must, to help
         * implement it in stages, but warn if we need to do so.
         */
-       if (type->mmu)
-       {
-               if (type->write_phys_memory == NULL)
-               {
-                       LOG_ERROR("type '%s' is missing write_phys_memory",
-                                       type->name);
-                       type->write_phys_memory = err_write_phys_memory;
-               }
-               if (type->read_phys_memory == NULL)
-               {
-                       LOG_ERROR("type '%s' is missing read_phys_memory",
-                                       type->name);
-                       type->read_phys_memory = err_read_phys_memory;
-               }
-               if (type->virt2phys == NULL)
-               {
+       if (type->mmu) {
+               if (type->virt2phys == NULL) {
                        LOG_ERROR("type '%s' is missing virt2phys", type->name);
                        type->virt2phys = identity_virt2phys;
                }
-       }
-       else
-       {
+       } else {
                /* Make sure no-MMU targets all behave the same:  make no
                 * distinction between physical and virtual addresses, and
                 * ensure that virt2phys() is always an identity mapping.
                 */
-               if (type->write_phys_memory || type->read_phys_memory
-                               || type->virt2phys)
-               {
+               if (type->write_phys_memory || type->read_phys_memory || type->virt2phys)
                        LOG_WARNING("type '%s' has bad MMU hooks", type->name);
-               }
 
                type->mmu = no_mmu;
                type->write_phys_memory = type->write_memory;
                type->read_phys_memory = type->read_memory;
                type->virt2phys = identity_virt2phys;
        }
+
+       if (target->type->read_buffer == NULL)
+               target->type->read_buffer = target_read_buffer_default;
+
+       if (target->type->write_buffer == NULL)
+               target->type->write_buffer = target_write_buffer_default;
+
+       if (target->type->get_gdb_fileio_info == NULL)
+               target->type->get_gdb_fileio_info = target_get_gdb_fileio_info_default;
+
+       if (target->type->gdb_fileio_end == NULL)
+               target->type->gdb_fileio_end = target_gdb_fileio_end_default;
+
+       if (target->type->profiling == NULL)
+               target->type->profiling = target_profiling_default;
+
        return ERROR_OK;
 }
 
@@ -853,8 +1343,7 @@ static int target_init(struct command_context *cmd_ctx)
        struct target *target;
        int retval;
 
-       for (target = all_targets; target; target = target->next)
-       {
+       for (target = all_targets; target; target = target->next) {
                retval = target_init_one(cmd_ctx, target);
                if (ERROR_OK != retval)
                        return retval;
@@ -877,32 +1366,43 @@ static int target_init(struct command_context *cmd_ctx)
 
 COMMAND_HANDLER(handle_target_init_command)
 {
+       int retval;
+
        if (CMD_ARGC != 0)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       static bool target_initialized = false;
-       if (target_initialized)
-       {
+       static bool target_initialized;
+       if (target_initialized) {
                LOG_INFO("'target init' has already been called");
                return ERROR_OK;
        }
        target_initialized = true;
 
+       retval = command_run_line(CMD_CTX, "init_targets");
+       if (ERROR_OK != retval)
+               return retval;
+
+       retval = command_run_line(CMD_CTX, "init_target_events");
+       if (ERROR_OK != retval)
+               return retval;
+
+       retval = command_run_line(CMD_CTX, "init_board");
+       if (ERROR_OK != retval)
+               return retval;
+
        LOG_DEBUG("Initializing targets...");
        return target_init(CMD_CTX);
 }
 
-int target_register_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv)
+int target_register_event_callback(int (*callback)(struct target *target,
+               enum target_event event, void *priv), void *priv)
 {
        struct target_event_callback **callbacks_p = &target_event_callbacks;
 
        if (callback == NULL)
-       {
-               return ERROR_INVALID_ARGUMENTS;
-       }
+               return ERROR_COMMAND_SYNTAX_ERROR;
 
-       if (*callbacks_p)
-       {
+       if (*callbacks_p) {
                while ((*callbacks_p)->next)
                        callbacks_p = &((*callbacks_p)->next);
                callbacks_p = &((*callbacks_p)->next);
@@ -916,18 +1416,59 @@ int target_register_event_callback(int (*callback)(struct target *target, enum t
        return ERROR_OK;
 }
 
-int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)
+int target_register_reset_callback(int (*callback)(struct target *target,
+               enum target_reset_mode reset_mode, void *priv), void *priv)
 {
-       struct target_timer_callback **callbacks_p = &target_timer_callbacks;
-       struct timeval now;
+       struct target_reset_callback *entry;
 
        if (callback == NULL)
-       {
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       entry = malloc(sizeof(struct target_reset_callback));
+       if (entry == NULL) {
+               LOG_ERROR("error allocating buffer for reset callback entry");
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       if (*callbacks_p)
-       {
+       entry->callback = callback;
+       entry->priv = priv;
+       list_add(&entry->list, &target_reset_callback_list);
+
+
+       return ERROR_OK;
+}
+
+int target_register_trace_callback(int (*callback)(struct target *target,
+               size_t len, uint8_t *data, void *priv), void *priv)
+{
+       struct target_trace_callback *entry;
+
+       if (callback == NULL)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       entry = malloc(sizeof(struct target_trace_callback));
+       if (entry == NULL) {
+               LOG_ERROR("error allocating buffer for trace callback entry");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       entry->callback = callback;
+       entry->priv = priv;
+       list_add(&entry->list, &target_trace_callback_list);
+
+
+       return ERROR_OK;
+}
+
+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;
+
+       if (callback == NULL)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       if (*callbacks_p) {
                while ((*callbacks_p)->next)
                        callbacks_p = &((*callbacks_p)->next);
                callbacks_p = &((*callbacks_p)->next);
@@ -935,18 +1476,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;
@@ -954,26 +1489,22 @@ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int
        return ERROR_OK;
 }
 
-int target_unregister_event_callback(int (*callback)(struct target *target, enum target_event event, void *priv), void *priv)
+int target_unregister_event_callback(int (*callback)(struct target *target,
+               enum target_event event, void *priv), void *priv)
 {
        struct target_event_callback **p = &target_event_callbacks;
        struct target_event_callback *c = target_event_callbacks;
 
        if (callback == NULL)
-       {
-               return ERROR_INVALID_ARGUMENTS;
-       }
+               return ERROR_COMMAND_SYNTAX_ERROR;
 
-       while (c)
-       {
+       while (c) {
                struct target_event_callback *next = c->next;
-               if ((c->callback == callback) && (c->priv == priv))
-               {
+               if ((c->callback == callback) && (c->priv == priv)) {
                        *p = next;
                        free(c);
                        return ERROR_OK;
-               }
-               else
+               } else
                        p = &(c->next);
                c = next;
        }
@@ -981,52 +1512,76 @@ int target_unregister_event_callback(int (*callback)(struct target *target, enum
        return ERROR_OK;
 }
 
-static int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
+int target_unregister_reset_callback(int (*callback)(struct target *target,
+               enum target_reset_mode reset_mode, void *priv), void *priv)
 {
-       struct target_timer_callback **p = &target_timer_callbacks;
-       struct target_timer_callback *c = target_timer_callbacks;
+       struct target_reset_callback *entry;
 
        if (callback == NULL)
-       {
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       list_for_each_entry(entry, &target_reset_callback_list, list) {
+               if (entry->callback == callback && entry->priv == priv) {
+                       list_del(&entry->list);
+                       free(entry);
+                       break;
+               }
        }
 
-       while (c)
-       {
-               struct target_timer_callback *next = c->next;
-               if ((c->callback == callback) && (c->priv == priv))
-               {
-                       *p = next;
-                       free(c);
-                       return ERROR_OK;
+       return ERROR_OK;
+}
+
+int target_unregister_trace_callback(int (*callback)(struct target *target,
+               size_t len, uint8_t *data, void *priv), void *priv)
+{
+       struct target_trace_callback *entry;
+
+       if (callback == NULL)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       list_for_each_entry(entry, &target_trace_callback_list, list) {
+               if (entry->callback == callback && entry->priv == priv) {
+                       list_del(&entry->list);
+                       free(entry);
+                       break;
                }
-               else
-                       p = &(c->next);
-               c = next;
        }
 
        return ERROR_OK;
 }
 
+int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
+{
+       if (callback == NULL)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       for (struct target_timer_callback *c = target_timer_callbacks;
+            c; c = c->next) {
+               if ((c->callback == callback) && (c->priv == priv)) {
+                       c->removed = true;
+                       return ERROR_OK;
+               }
+       }
+
+       return ERROR_FAIL;
+}
+
 int target_call_event_callbacks(struct target *target, enum target_event event)
 {
        struct target_event_callback *callback = target_event_callbacks;
        struct target_event_callback *next_callback;
 
-       if (event == TARGET_EVENT_HALTED)
-       {
+       if (event == TARGET_EVENT_HALTED) {
                /* execute early halted first */
                target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
        }
 
-       LOG_DEBUG("target event %i (%s)",
-                         event,
-                         Jim_Nvp_value2name_simple(nvp_target_event, event)->name);
+       LOG_DEBUG("target event %i (%s)", event,
+                       Jim_Nvp_value2name_simple(nvp_target_event, event)->name);
 
        target_handle_event(target, event);
 
-       while (callback)
-       {
+       while (callback) {
                next_callback = callback->next;
                callback->callback(target, event, callback->priv);
                callback = next_callback;
@@ -1035,18 +1590,34 @@ int target_call_event_callbacks(struct target *target, enum target_event event)
        return ERROR_OK;
 }
 
+int target_call_reset_callbacks(struct target *target, enum target_reset_mode reset_mode)
+{
+       struct target_reset_callback *callback;
+
+       LOG_DEBUG("target reset %i (%s)", reset_mode,
+                       Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name);
+
+       list_for_each_entry(callback, &target_reset_callback_list, list)
+               callback->callback(target, reset_mode, callback->priv);
+
+       return ERROR_OK;
+}
+
+int target_call_trace_callbacks(struct target *target, size_t len, uint8_t *data)
+{
+       struct target_trace_callback *callback;
+
+       list_for_each_entry(callback, &target_trace_callback_list, list)
+               callback->callback(target, len, data, callback->priv);
+
+       return ERROR_OK;
+}
+
 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;
 }
 
@@ -1055,7 +1626,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);
@@ -1063,33 +1634,42 @@ static int target_call_timer_callback(struct target_timer_callback *cb,
 
 static int target_call_timer_callbacks_check_time(int checktime)
 {
+       static bool callback_processing;
+
+       /* Do not allow nesting */
+       if (callback_processing)
+               return ERROR_OK;
+
+       callback_processing = true;
+
        keep_alive();
 
        struct timeval now;
        gettimeofday(&now, NULL);
 
-       struct target_timer_callback *callback = target_timer_callbacks;
-       while (callback)
-       {
-               // cleaning up may unregister and free this callback
-               struct target_timer_callback *next_callback = callback->next;
+       /* Store an address of the place containing a pointer to the
+        * next item; initially, that's a standalone "root of the
+        * list" variable. */
+       struct target_timer_callback **callback = &target_timer_callbacks;
+       while (*callback) {
+               if ((*callback)->removed) {
+                       struct target_timer_callback *p = *callback;
+                       *callback = (*callback)->next;
+                       free(p);
+                       continue;
+               }
 
-               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));
+               bool call_it = (*callback)->callback &&
+                       ((!checktime && (*callback)->type == TARGET_TIMER_TYPE_PERIODIC) ||
+                        timeval_compare(&now, &(*callback)->when) >= 0);
 
                if (call_it)
-               {
-                       int retval = target_call_timer_callback(callback, &now);
-                       if (retval != ERROR_OK)
-                               return retval;
-               }
+                       target_call_timer_callback(*callback, &now);
 
-               callback = next_callback;
+               callback = &(*callback)->next;
        }
 
+       callback_processing = false;
        return ERROR_OK;
 }
 
@@ -1104,28 +1684,99 @@ int target_call_timer_callbacks_now(void)
        return target_call_timer_callbacks_check_time(0);
 }
 
-int target_alloc_working_area_try(struct target *target, uint32_t size, struct working_area **area)
+/* Prints the working area layout for debug purposes */
+static void print_wa_layout(struct target *target)
+{
+       struct working_area *c = target->working_areas;
+
+       while (c) {
+               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;
+       }
+}
+
+/* Reduce area to size bytes, create a new free area from the remaining bytes, if any. */
+static void target_split_working_area(struct working_area *area, uint32_t size)
+{
+       assert(area->free); /* Shouldn't split an allocated area */
+       assert(size <= area->size); /* Caller should guarantee this */
+
+       /* Split only if not already the right size */
+       if (size < area->size) {
+               struct working_area *new_wa = malloc(sizeof(*new_wa));
+
+               if (new_wa == NULL)
+                       return;
+
+               new_wa->next = area->next;
+               new_wa->size = area->size - size;
+               new_wa->address = area->address + size;
+               new_wa->backup = NULL;
+               new_wa->user = NULL;
+               new_wa->free = true;
+
+               area->next = new_wa;
+               area->size = size;
+
+               /* If backup memory was allocated to this area, it has the wrong size
+                * now so free it and it will be reallocated if/when needed */
+               if (area->backup) {
+                       free(area->backup);
+                       area->backup = NULL;
+               }
+       }
+}
+
+/* Merge all adjacent free areas into one */
+static void target_merge_working_areas(struct target *target)
 {
        struct working_area *c = target->working_areas;
-       struct working_area *new_wa = NULL;
 
+       while (c && c->next) {
+               assert(c->next->address == c->address + c->size); /* This is an invariant */
+
+               /* Find two adjacent free areas */
+               if (c->free && c->next->free) {
+                       /* Merge the last into the first */
+                       c->size += c->next->size;
+
+                       /* Remove the last */
+                       struct working_area *to_be_freed = c->next;
+                       c->next = c->next->next;
+                       if (to_be_freed->backup)
+                               free(to_be_freed->backup);
+                       free(to_be_freed);
+
+                       /* If backup memory was allocated to the remaining area, it's has
+                        * the wrong size now */
+                       if (c->backup) {
+                               free(c->backup);
+                               c->backup = NULL;
+                       }
+               } else {
+                       c = c->next;
+               }
+       }
+}
+
+int target_alloc_working_area_try(struct target *target, uint32_t size, struct working_area **area)
+{
        /* Reevaluate working area address based on MMU state*/
-       if (target->working_areas == NULL)
-       {
+       if (target->working_areas == NULL) {
                int retval;
                int enabled;
 
                retval = target->type->mmu(target, &enabled);
                if (retval != ERROR_OK)
-               {
                        return retval;
-               }
 
                if (!enabled) {
                        if (target->working_area_phys_spec) {
                                LOG_DEBUG("MMU disabled, using physical "
-                                       "address for working memory 0x%08x",
-                                       (unsigned)target->working_area_phys);
+                                       "address for working memory " TARGET_ADDR_FMT,
+                                       target->working_area_phys);
                                target->working_area = target->working_area_phys;
                        } else {
                                LOG_ERROR("No working memory available. "
@@ -1135,8 +1786,8 @@ 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%08x",
-                                       (unsigned)target->working_area_virt);
+                                       "address for working memory " TARGET_ADDR_FMT,
+                                       target->working_area_virt);
                                target->working_area = target->working_area_virt;
                        } else {
                                LOG_ERROR("No working memory available. "
@@ -1144,80 +1795,63 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w
                                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                        }
                }
+
+               /* Set up initial working area on first call */
+               struct working_area *new_wa = malloc(sizeof(*new_wa));
+               if (new_wa) {
+                       new_wa->next = NULL;
+                       new_wa->size = target->working_area_size & ~3UL; /* 4-byte align */
+                       new_wa->address = target->working_area;
+                       new_wa->backup = NULL;
+                       new_wa->user = NULL;
+                       new_wa->free = true;
+               }
+
+               target->working_areas = new_wa;
        }
 
        /* only allocate multiples of 4 byte */
        if (size % 4)
-       {
-               LOG_ERROR("BUG: code tried to allocate unaligned number of bytes (0x%08x), padding", ((unsigned)(size)));
-               size = (size + 3) & (~3);
-       }
+               size = (size + 3) & (~3UL);
 
-       /* see if there's already a matching working area */
-       while (c)
-       {
-               if ((c->free) && (c->size == size))
-               {
-                       new_wa = c;
+       struct working_area *c = target->working_areas;
+
+       /* Find the first large enough working area */
+       while (c) {
+               if (c->free && c->size >= size)
                        break;
-               }
                c = c->next;
        }
 
-       /* if not, allocate a new one */
-       if (!new_wa)
-       {
-               struct working_area **p = &target->working_areas;
-               uint32_t first_free = target->working_area;
-               uint32_t free_size = target->working_area_size;
-
-               c = target->working_areas;
-               while (c)
-               {
-                       first_free += c->size;
-                       free_size -= c->size;
-                       p = &c->next;
-                       c = c->next;
-               }
-
-               if (free_size < size)
-               {
-                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-               }
+       if (c == NULL)
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
 
-               LOG_DEBUG("allocated new working area at address 0x%08x", (unsigned)first_free);
+       /* Split the working area into the requested size */
+       target_split_working_area(c, size);
 
-               new_wa = malloc(sizeof(struct working_area));
-               new_wa->next = NULL;
-               new_wa->size = size;
-               new_wa->address = first_free;
+       LOG_DEBUG("allocated new working area of %" PRIu32 " bytes at address " TARGET_ADDR_FMT,
+                         size, c->address);
 
-               if (target->backup_working_area)
-               {
-                       int retval;
-                       new_wa->backup = malloc(new_wa->size);
-                       if ((retval = target_read_memory(target, new_wa->address, 4, new_wa->size / 4, new_wa->backup)) != ERROR_OK)
-                       {
-                               free(new_wa->backup);
-                               free(new_wa);
-                               return retval;
-                       }
-               }
-               else
-               {
-                       new_wa->backup = NULL;
+       if (target->backup_working_area) {
+               if (c->backup == NULL) {
+                       c->backup = malloc(c->size);
+                       if (c->backup == NULL)
+                               return ERROR_FAIL;
                }
 
-               /* put new entry in list */
-               *p = new_wa;
+               int retval = target_read_memory(target, c->address, 4, c->size / 4, c->backup);
+               if (retval != ERROR_OK)
+                       return retval;
        }
 
        /* mark as used, and return the new (reused) area */
-       new_wa->free = false;
-       *area = new_wa;
+       c->free = false;
+       *area = c;
 
        /* user pointer */
-       new_wa->user = area;
+       c->user = area;
+
+       print_wa_layout(target);
 
        return ERROR_OK;
 }
@@ -1228,32 +1862,57 @@ int target_alloc_working_area(struct target *target, uint32_t size, struct worki
 
        retval = target_alloc_working_area_try(target, size, area);
        if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
-       {
-               LOG_WARNING("not enough working area available(requested %u)", (unsigned)(size));
-       }
+               LOG_WARNING("not enough working area available(requested %"PRIu32")", size);
        return retval;
 
 }
 
+static int target_restore_working_area(struct target *target, struct working_area *area)
+{
+       int retval = ERROR_OK;
+
+       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 " TARGET_ADDR_FMT,
+                                       area->size, area->address);
+       }
+
+       return retval;
+}
+
+/* Restore the area's backup memory, if any, and return the area to the allocation pool */
 static int target_free_working_area_restore(struct target *target, struct working_area *area, int restore)
 {
+       int retval = ERROR_OK;
+
        if (area->free)
-               return ERROR_OK;
+               return retval;
 
-       if (restore && target->backup_working_area)
-       {
-               int retval;
-               if ((retval = target_write_memory(target, area->address, 4, area->size / 4, area->backup)) != ERROR_OK)
+       if (restore) {
+               retval = target_restore_working_area(target, area);
+               /* REVISIT: Perhaps the area should be freed even if restoring fails. */
+               if (retval != ERROR_OK)
                        return retval;
        }
 
        area->free = true;
 
+       LOG_DEBUG("freed %" PRIu32 " bytes of working area at address " TARGET_ADDR_FMT,
+                       area->size, area->address);
+
        /* mark user pointer invalid */
+       /* TODO: Is this really safe? It points to some previous caller's memory.
+        * How could we know that the area pointer is still in that place and not
+        * some other vital data? What's the purpose of this, anyway? */
        *area->user = NULL;
        area->user = NULL;
 
-       return ERROR_OK;
+       target_merge_working_areas(target);
+
+       print_wa_layout(target);
+
+       return retval;
 }
 
 int target_free_working_area(struct target *target, struct working_area *area)
@@ -1268,38 +1927,135 @@ static void target_free_all_working_areas_restore(struct target *target, int res
 {
        struct working_area *c = target->working_areas;
 
-       while (c)
-       {
-               struct working_area *next = c->next;
-               target_free_working_area_restore(target, c, restore);
-
-               if (c->backup)
-                       free(c->backup);
-
-               free(c);
+       LOG_DEBUG("freeing all working areas");
 
-               c = next;
+       /* Loop through all areas, restoring the allocated ones and marking them as free */
+       while (c) {
+               if (!c->free) {
+                       if (restore)
+                               target_restore_working_area(target, c);
+                       c->free = true;
+                       *c->user = NULL; /* Same as above */
+                       c->user = NULL;
+               }
+               c = c->next;
        }
 
-       target->working_areas = NULL;
+       /* Run a merge pass to combine all areas into one */
+       target_merge_working_areas(target);
+
+       print_wa_layout(target);
 }
 
 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 */
+uint32_t target_get_working_area_avail(struct target *target)
+{
+       struct working_area *c = target->working_areas;
+       uint32_t max_size = 0;
+
+       if (c == NULL)
+               return target->working_area_size;
+
+       while (c) {
+               if (c->free && max_size < c->size)
+                       max_size = c->size;
+
+               c = c->next;
+       }
+
+       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");
+       if (target == NULL) {
+               LOG_WARNING("No target has been configured");
                return ERROR_OK;
        }
 
-       LOG_USER("target state: %s", target_state_name( target ));
-
        if (target->state != TARGET_HALTED)
                return ERROR_OK;
 
@@ -1307,83 +2063,127 @@ int target_arch_state(struct target *target)
        return retval;
 }
 
+static int target_get_gdb_fileio_info_default(struct target *target,
+               struct gdb_fileio_info *fileio_info)
+{
+       /* If target does not support semi-hosting function, target
+          has no need to provide .get_gdb_fileio_info callback.
+          It just return ERROR_FAIL and gdb_server will return "Txx"
+          as target halted every time.  */
+       return ERROR_FAIL;
+}
+
+static int target_gdb_fileio_end_default(struct target *target,
+               int retcode, int fileio_errno, bool ctrl_c)
+{
+       return ERROR_OK;
+}
+
+static int target_profiling_default(struct target *target, uint32_t *samples,
+               uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
+{
+       struct timeval timeout, now;
+
+       gettimeofday(&timeout, NULL);
+       timeval_add_time(&timeout, seconds, 0);
+
+       LOG_INFO("Starting profiling. Halting and resuming the"
+                       " target as often as we can...");
+
+       uint32_t sample_count = 0;
+       /* hopefully it is safe to cache! We want to stop/restart as quickly as possible. */
+       struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1);
+
+       int retval = ERROR_OK;
+       for (;;) {
+               target_poll(target);
+               if (target->state == TARGET_HALTED) {
+                       uint32_t t = buf_get_u32(reg->value, 0, 32);
+                       samples[sample_count++] = t;
+                       /* current pc, addr = 0, do not handle breakpoints, not debugging */
+                       retval = target_resume(target, 1, 0, 0, 0);
+                       target_poll(target);
+                       alive_sleep(10); /* sleep 10ms, i.e. <100 samples/second. */
+               } else if (target->state == TARGET_RUNNING) {
+                       /* We want to quickly sample the PC. */
+                       retval = target_halt(target);
+               } else {
+                       LOG_INFO("Target not halted or running");
+                       retval = ERROR_OK;
+                       break;
+               }
+
+               if (retval != ERROR_OK)
+                       break;
+
+               gettimeofday(&now, NULL);
+               if ((sample_count >= max_num_samples) || timeval_compare(&now, &timeout) >= 0) {
+                       LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count);
+                       break;
+               }
+       }
+
+       *num_samples = sample_count;
+       return retval;
+}
+
 /* Single aligned words are guaranteed to use 16 or 32 bit access
  * mode respectively, otherwise data is handled as quickly as
  * possible
  */
-int target_write_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer)
+int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
 {
-       int retval;
-       LOG_DEBUG("writing buffer of %i byte at 0x%8.8x",
-                 (int)size, (unsigned)address);
+       LOG_DEBUG("writing buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT,
+                         size, address);
 
-       if (!target_was_examined(target))
-       {
+       if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
 
-       if (size == 0) {
+       if (size == 0)
                return ERROR_OK;
-       }
 
-       if ((address + size - 1) < address)
-       {
-               /* GDB can request this when e.g. PC is 0xfffffffc*/
-               LOG_ERROR("address + size wrapped(0x%08x, 0x%08x)",
-                                 (unsigned)address,
-                                 (unsigned)size);
+       if ((address + size - 1) < address) {
+               /* GDB can request this when e.g. PC is 0xfffffffc */
+               LOG_ERROR("address + size wrapped (" TARGET_ADDR_FMT ", 0x%08" PRIx32 ")",
+                                 address,
+                                 size);
                return ERROR_FAIL;
        }
 
-       if (((address % 2) == 0) && (size == 2))
-       {
-               return target_write_memory(target, address, 2, 1, buffer);
-       }
-
-       /* handle unaligned head bytes */
-       if (address % 4)
-       {
-               uint32_t unaligned = 4 - (address % 4);
-
-               if (unaligned > size)
-                       unaligned = size;
-
-               if ((retval = target_write_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
-                       return retval;
-
-               buffer += unaligned;
-               address += unaligned;
-               size -= unaligned;
-       }
+       return target->type->write_buffer(target, address, size, buffer);
+}
 
-       /* handle aligned words */
-       if (size >= 4)
-       {
-               int aligned = size - (size % 4);
+static int target_write_buffer_default(struct target *target,
+       target_addr_t address, uint32_t count, const uint8_t *buffer)
+{
+       uint32_t size;
 
-               /* use bulk writes above a certain limit. This may have to be changed */
-               if (aligned > 128)
-               {
-                       if ((retval = target->type->bulk_write_memory(target, address, aligned / 4, buffer)) != ERROR_OK)
-                               return retval;
-               }
-               else
-               {
-                       if ((retval = target_write_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
+       /* Align up to maximum 4 bytes. The loop condition makes sure the next pass
+        * will have something to do with the size we leave to it. */
+       for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
+               if (address & size) {
+                       int retval = target_write_memory(target, address, size, 1, buffer);
+                       if (retval != ERROR_OK)
                                return retval;
+                       address += size;
+                       count -= size;
+                       buffer += size;
                }
-
-               buffer += aligned;
-               address += aligned;
-               size -= aligned;
        }
 
-       /* handle tail writes of less than 4 bytes */
-       if (size > 0)
-       {
-               if ((retval = target_write_memory(target, address, 1, size, buffer)) != ERROR_OK)
-                       return retval;
+       /* Write the data with as large access size as possible. */
+       for (; size > 0; size /= 2) {
+               uint32_t aligned = count - count % size;
+               if (aligned > 0) {
+                       int retval = target_write_memory(target, address, size, aligned / size, buffer);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       address += aligned;
+                       count -= aligned;
+                       buffer += aligned;
+               }
        }
 
        return ERROR_OK;
@@ -1393,118 +2193,89 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size,
  * 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)
 {
-       int retval;
-       LOG_DEBUG("reading buffer of %i byte at 0x%8.8x",
-                         (int)size, (unsigned)address);
+       LOG_DEBUG("reading buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT,
+                         size, address);
 
-       if (!target_was_examined(target))
-       {
+       if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
 
-       if (size == 0) {
+       if (size == 0)
                return ERROR_OK;
-       }
 
-       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 ")",
+       if ((address + size - 1) < address) {
+               /* GDB can request this when e.g. PC is 0xfffffffc */
+               LOG_ERROR("address + size wrapped (" TARGET_ADDR_FMT ", 0x%08" PRIx32 ")",
                                  address,
                                  size);
                return ERROR_FAIL;
        }
 
-       if (((address % 2) == 0) && (size == 2))
-       {
-               return target_read_memory(target, address, 2, 1, buffer);
-       }
-
-       /* handle unaligned head bytes */
-       if (address % 4)
-       {
-               uint32_t unaligned = 4 - (address % 4);
-
-               if (unaligned > size)
-                       unaligned = size;
-
-               if ((retval = target_read_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
-                       return retval;
-
-               buffer += unaligned;
-               address += unaligned;
-               size -= unaligned;
-       }
-
-       /* handle aligned words */
-       if (size >= 4)
-       {
-               int aligned = size - (size % 4);
+       return target->type->read_buffer(target, address, size, buffer);
+}
 
-               if ((retval = target_read_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
-                       return retval;
+static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer)
+{
+       uint32_t size;
 
-               buffer += aligned;
-               address += aligned;
-               size -= aligned;
+       /* Align up to maximum 4 bytes. The loop condition makes sure the next pass
+        * will have something to do with the size we leave to it. */
+       for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
+               if (address & size) {
+                       int retval = target_read_memory(target, address, size, 1, buffer);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       address += size;
+                       count -= size;
+                       buffer += size;
+               }
        }
 
-       /*prevent byte access when possible (avoid AHB access limitations in some cases)*/
-       if(size >=2)
-       {
-               int aligned = size - (size%2);
-               retval = target_read_memory(target, address, 2, aligned / 2, buffer);
-               if (retval != ERROR_OK)
-                       return retval;
-
-               buffer += aligned;
-               address += aligned;
-               size -= aligned;
-       }
-       /* handle tail writes of less than 4 bytes */
-       if (size > 0)
-       {
-               if ((retval = target_read_memory(target, address, 1, size, buffer)) != ERROR_OK)
-                       return retval;
+       /* Read the data with as large access size as possible. */
+       for (; size > 0; size /= 2) {
+               uint32_t aligned = count - count % size;
+               if (aligned > 0) {
+                       int retval = target_read_memory(target, address, size, aligned / size, buffer);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       address += aligned;
+                       count -= aligned;
+                       buffer += aligned;
+               }
        }
 
        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;
        uint32_t i;
        uint32_t checksum = 0;
-       if (!target_was_examined(target))
-       {
+       if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
 
-       if ((retval = target->type->checksum_memory(target, address,
-               size, &checksum)) != ERROR_OK)
-       {
+       retval = target->type->checksum_memory(target, address, size, &checksum);
+       if (retval != ERROR_OK) {
                buffer = malloc(size);
-               if (buffer == NULL)
-               {
-                       LOG_ERROR("error allocating buffer for section (%d bytes)", (int)size);
-                       return ERROR_INVALID_ARGUMENTS;
+               if (buffer == NULL) {
+                       LOG_ERROR("error allocating buffer for section (%" PRId32 " bytes)", size);
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                }
                retval = target_read_buffer(target, address, size, buffer);
-               if (retval != ERROR_OK)
-               {
+               if (retval != ERROR_OK) {
                        free(buffer);
                        return retval;
                }
 
-               /* convert to target endianess */
-               for (i = 0; i < (size/sizeof(uint32_t)); i++)
-               {
+               /* convert to target endianness */
+               for (i = 0; i < (size/sizeof(uint32_t)); i++) {
                        uint32_t target_data;
                        target_data = target_buffer_get_u32(target, &buffer[i*sizeof(uint32_t)]);
                        target_buffer_set_u32(target, &buffer[i*sizeof(uint32_t)], target_data);
@@ -1519,223 +2290,340 @@ 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))
-       {
+       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);
+       return target->type->blank_check_memory(target, blocks, num_blocks, erased_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)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       int retval = target_read_memory(target, address, 8, 1, value_buf);
+
+       if (retval == ERROR_OK) {
+               *value = target_buffer_get_u64(target, value_buf);
+               LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "",
+                                 address,
+                                 *value);
+       } else {
+               *value = 0x0;
+               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))
-       {
+       if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
 
        int retval = target_read_memory(target, address, 4, 1, value_buf);
 
-       if (retval == ERROR_OK)
-       {
+       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
-       {
+       } 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))
-       {
+       if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
 
        int retval = target_read_memory(target, address, 2, 1, value_buf);
 
-       if (retval == ERROR_OK)
-       {
+       if (retval == ERROR_OK) {
                *value = target_buffer_get_u16(target, value_buf);
-               LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%4.4x",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%4.4" PRIx16,
                                  address,
                                  *value);
-       }
-       else
-       {
+       } 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)
 {
-       int retval = target_read_memory(target, address, 1, 1, value);
-       if (!target_was_examined(target))
-       {
+       if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
 
-       if (retval == ERROR_OK)
-       {
-               LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x",
+       int retval = target_read_memory(target, address, 1, 1, value);
+
+       if (retval == ERROR_OK) {
+               LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8,
                                  address,
                                  *value);
-       }
-       else
-       {
+       } else {
                *value = 0x0;
-               LOG_DEBUG("address: 0x%8.8" PRIx32 " failed",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT " failed",
                                  address);
        }
 
        return retval;
 }
 
-int target_write_u32(struct target *target, uint32_t address, uint32_t value)
+int target_write_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_memory(target, address, 8, 1, value_buf);
+       if (retval != ERROR_OK)
+               LOG_DEBUG("failed: %i", retval);
+
+       return retval;
+}
+
+int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
 {
        int retval;
        uint8_t value_buf[4];
-       if (!target_was_examined(target))
-       {
+       if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                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);
 
        target_buffer_set_u32(target, value_buf, value);
-       if ((retval = target_write_memory(target, address, 4, 1, value_buf)) != ERROR_OK)
-       {
+       retval = target_write_memory(target, address, 4, 1, value_buf);
+       if (retval != ERROR_OK)
                LOG_DEBUG("failed: %i", retval);
-       }
 
        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];
-       if (!target_was_examined(target))
-       {
+       if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
 
-       LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8x",
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx16,
                          address,
                          value);
 
        target_buffer_set_u16(target, value_buf, value);
-       if ((retval = target_write_memory(target, address, 2, 1, value_buf)) != ERROR_OK)
-       {
+       retval = target_write_memory(target, address, 2, 1, value_buf);
+       if (retval != ERROR_OK)
                LOG_DEBUG("failed: %i", retval);
-       }
 
        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))
-       {
+       if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
 
-       LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x",
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8,
                          address, value);
 
-       if ((retval = target_write_memory(target, address, 1, 1, &value)) != ERROR_OK)
-       {
+       retval = target_write_memory(target, address, 1, 1, &value);
+       if (retval != ERROR_OK)
                LOG_DEBUG("failed: %i", retval);
+
+       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;
 }
 
-COMMAND_HANDLER(handle_targets_command)
+int target_write_phys_u32(struct target *target, target_addr_t address, uint32_t value)
 {
-       struct target *target = all_targets;
+       int retval;
+       uint8_t value_buf[4];
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
 
-       if (CMD_ARGC == 1)
-       {
-               target = get_target(CMD_ARGV[0]);
-               if (target == NULL) {
-                       command_print(CMD_CTX,"Target: %s is unknown, try one of:\n", CMD_ARGV[0]);
-                       goto DumpTargets;
-               }
-               if (!target->tap->enabled) {
-                       command_print(CMD_CTX,"Target: TAP %s is disabled, "
-                                       "can't be the current target\n",
-                                       target->tap->dotted_name);
-                       return ERROR_FAIL;
-               }
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "",
+                         address,
+                         value);
 
-               CMD_CTX->current_target = target->target_number;
-               return ERROR_OK;
+       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);
+       if (target == NULL) {
+               LOG_ERROR("Target: %s is unknown, try one of:\n", name);
+               return ERROR_FAIL;
+       }
+       if (!target->tap->enabled) {
+               LOG_USER("Target: TAP %s is disabled, "
+                        "can't be the current target\n",
+                        target->tap->dotted_name);
+               return ERROR_FAIL;
+       }
+
+       cmd_ctx->current_target = target;
+       if (cmd_ctx->current_target_override)
+               cmd_ctx->current_target_override = target;
+
+       return ERROR_OK;
+}
+
+
+COMMAND_HANDLER(handle_targets_command)
+{
+       int retval = ERROR_OK;
+       if (CMD_ARGC == 1) {
+               retval = find_target(CMD_CTX, CMD_ARGV[0]);
+               if (retval == ERROR_OK) {
+                       /* we're done! */
+                       return retval;
+               }
        }
-DumpTargets:
 
-       target = all_targets;
+       struct target *target = all_targets;
        command_print(CMD_CTX, "    TargetName         Type       Endian TapName            State       ");
        command_print(CMD_CTX, "--  ------------------ ---------- ------ ------------------ ------------");
-       while (target)
-       {
+       while (target) {
                const char *state;
                char marker = ' ';
 
                if (target->tap->enabled)
-                       state = target_state_name( target );
+                       state = target_state_name(target);
                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 */
-               command_print(CMD_CTX, "%2d%c %-18s %-10s %-6s %-18s %s",
-                                         target->target_number,
-                                         marker,
-                                         target_name(target),
-                                         target_type_name(target),
-                                         Jim_Nvp_value2name_simple(nvp_target_endian,
-                                                               target->endianness)->name,
-                                         target->tap->dotted_name,
-                                         state);
+               command_print(CMD_CTX,
+                               "%2d%c %-18s %-10s %-6s %-18s %s",
+                               target->target_number,
+                               marker,
+                               target_name(target),
+                               target_type_name(target),
+                               Jim_Nvp_value2name_simple(nvp_target_endian,
+                                       target->endianness)->name,
+                               target->tap->dotted_name,
+                               state);
                target = target->next;
        }
 
-       return ERROR_OK;
+       return retval;
 }
 
 /* every 300ms we check for reset & powerdropout and issue a "reset halt" if so. */
@@ -1750,53 +2638,47 @@ static int runSrstDeasserted;
 
 static int sense_handler(void)
 {
-       static int prevSrstAsserted = 0;
-       static int prevPowerdropout = 0;
+       static int prevSrstAsserted;
+       static int prevPowerdropout;
 
-       int retval;
-       if ((retval = jtag_power_dropout(&powerDropout)) != ERROR_OK)
+       int retval = jtag_power_dropout(&powerDropout);
+       if (retval != ERROR_OK)
                return retval;
 
        int powerRestored;
        powerRestored = prevPowerdropout && !powerDropout;
        if (powerRestored)
-       {
                runPowerRestore = 1;
-       }
 
-       long long current = timeval_ms();
-       static long long lastPower = 0;
-       int waitMore = lastPower + 2000 > current;
-       if (powerDropout && !waitMore)
-       {
+       int64_t current = timeval_ms();
+       static int64_t lastPower;
+       bool waitMore = lastPower + 2000 > current;
+       if (powerDropout && !waitMore) {
                runPowerDropout = 1;
                lastPower = current;
        }
 
-       if ((retval = jtag_srst_asserted(&srstAsserted)) != ERROR_OK)
+       retval = jtag_srst_asserted(&srstAsserted);
+       if (retval != ERROR_OK)
                return retval;
 
        int srstDeasserted;
        srstDeasserted = prevSrstAsserted && !srstAsserted;
 
-       static long long lastSrst = 0;
+       static int64_t lastSrst;
        waitMore = lastSrst + 2000 > current;
-       if (srstDeasserted && !waitMore)
-       {
+       if (srstDeasserted && !waitMore) {
                runSrstDeasserted = 1;
                lastSrst = current;
        }
 
        if (!prevSrstAsserted && srstAsserted)
-       {
                runSrstAsserted = 1;
-       }
 
        prevSrstAsserted = srstAsserted;
        prevPowerdropout = powerDropout;
 
-       if (srstDeasserted || powerRestored)
-       {
+       if (srstDeasserted || powerRestored) {
                /* Other than logging the event we can't do anything here.
                 * Issuing a reset is a particularly bad idea as we might
                 * be inside a reset already.
@@ -1806,25 +2688,20 @@ static int sense_handler(void)
        return ERROR_OK;
 }
 
-static int backoff_times = 0;
-static int backoff_count = 0;
-
 /* process target state changes */
 static int handle_target(void *priv)
 {
        Jim_Interp *interp = (Jim_Interp *)priv;
        int retval = ERROR_OK;
 
-       if (!is_jtag_poll_safe())
-       {
+       if (!is_jtag_poll_safe()) {
                /* polling is disabled currently */
                return ERROR_OK;
        }
 
        /* we do not want to recurse here... */
-       static int recursive = 0;
-       if (! recursive)
-       {
+       static int recursive;
+       if (!recursive) {
                recursive = 1;
                sense_handler();
                /* danger! running these procedures can trigger srst assertions and power dropouts.
@@ -1832,31 +2709,26 @@ static int handle_target(void *priv)
                 * clearing the flags after running these events.
                 */
                int did_something = 0;
-               if (runSrstAsserted)
-               {
+               if (runSrstAsserted) {
                        LOG_INFO("srst asserted detected, running srst_asserted proc.");
                        Jim_Eval(interp, "srst_asserted");
                        did_something = 1;
                }
-               if (runSrstDeasserted)
-               {
+               if (runSrstDeasserted) {
                        Jim_Eval(interp, "srst_deasserted");
                        did_something = 1;
                }
-               if (runPowerDropout)
-               {
+               if (runPowerDropout) {
                        LOG_INFO("Power dropout detected, running power_dropout proc.");
                        Jim_Eval(interp, "power_dropout");
                        did_something = 1;
                }
-               if (runPowerRestore)
-               {
+               if (runPowerRestore) {
                        Jim_Eval(interp, "power_restore");
                        did_something = 1;
                }
 
-               if (did_something)
-               {
+               if (did_something) {
                        /* clear detect flags */
                        sense_handler();
                }
@@ -1871,50 +2743,58 @@ static int handle_target(void *priv)
                recursive = 0;
        }
 
-       if (backoff_times > backoff_count)
-       {
-               /* do not poll this time as we failed previously */
-               backoff_count++;
-               return ERROR_OK;
-       }
-       backoff_count = 0;
-
        /* Poll targets for state changes unless that's globally disabled.
         * Skip targets that are currently disabled.
         */
        for (struct target *target = all_targets;
                        is_jtag_poll_safe() && target;
-                       target = target->next)
-       {
+                       target = target->next) {
+
+               if (!target_was_examined(target))
+                       continue;
+
                if (!target->tap->enabled)
                        continue;
 
+               if (target->backoff.times > target->backoff.count) {
+                       /* do not poll this time as we failed previously */
+                       target->backoff.count++;
+                       continue;
+               }
+               target->backoff.count = 0;
+
                /* only poll target if we've got power and srst isn't asserted */
-               if (!powerDropout && !srstAsserted)
-               {
+               if (!powerDropout && !srstAsserted) {
                        /* polling may fail silently until the target has been examined */
-                       if ((retval = target_poll(target)) != ERROR_OK)
-                       {
+                       retval = target_poll(target);
+                       if (retval != ERROR_OK) {
                                /* 100ms polling interval. Increase interval between polling up to 5000ms */
-                               if (backoff_times * polling_interval < 5000)
-                               {
-                                       backoff_times *= 2;
-                                       backoff_times++;
+                               if (target->backoff.times * polling_interval < 5000) {
+                                       target->backoff.times *= 2;
+                                       target->backoff.times++;
                                }
-                               LOG_USER("Polling target failed, GDB will be halted. Polling again in %dms", backoff_times * polling_interval);
 
                                /* Tell GDB to halt the debugger. This allows the user to
                                 * run monitor commands to handle the situation.
                                 */
                                target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
-                               return retval;
                        }
-                       /* Since we succeeded, we reset backoff count */
-                       if (backoff_times > 0)
-                       {
-                               LOG_USER("Polling succeeded again");
+                       if (target->backoff.times > 0) {
+                               LOG_USER("Polling target %s failed, trying to reexamine", target_name(target));
+                               target_reset_examined(target);
+                               retval = target_examine_one(target);
+                               /* Target examination could have failed due to unstable connection,
+                                * but we set the examined flag anyway to repoll it later */
+                               if (retval != ERROR_OK) {
+                                       target->examined = true;
+                                       LOG_USER("Examination failed, GDB will be halted. Polling again in %dms",
+                                                target->backoff.times * polling_interval);
+                                       return retval;
+                               }
                        }
-                       backoff_times = 0;
+
+                       /* Since we succeeded, we reset backoff count */
+                       target->backoff.times = 0;
                }
        }
 
@@ -1933,21 +2813,20 @@ COMMAND_HANDLER(handle_reg_command)
        target = get_current_target(CMD_CTX);
 
        /* list all available registers for the current target */
-       if (CMD_ARGC == 0)
-       {
+       if (CMD_ARGC == 0) {
                struct reg_cache *cache = target->reg_cache;
 
                count = 0;
-               while (cache)
-               {
+               while (cache) {
                        unsigned i;
 
                        command_print(CMD_CTX, "===== %s", cache->name);
 
                        for (i = 0, reg = cache->reg_list;
                                        i < cache->num_regs;
-                                       i++, reg++, count++)
-                       {
+                                       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,
@@ -1973,20 +2852,16 @@ COMMAND_HANDLER(handle_reg_command)
        }
 
        /* access a single register by its ordinal number */
-       if ((CMD_ARGV[0][0] >= '0') && (CMD_ARGV[0][0] <= '9'))
-       {
+       if ((CMD_ARGV[0][0] >= '0') && (CMD_ARGV[0][0] <= '9')) {
                unsigned num;
                COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
 
                struct reg_cache *cache = target->reg_cache;
                count = 0;
-               while (cache)
-               {
+               while (cache) {
                        unsigned i;
-                       for (i = 0; i < cache->num_regs; i++)
-                       {
-                               if (count++ == num)
-                               {
+                       for (i = 0; i < cache->num_regs; i++) {
+                               if (count++ == num) {
                                        reg = &cache->reg_list[i];
                                        break;
                                }
@@ -1996,32 +2871,32 @@ COMMAND_HANDLER(handle_reg_command)
                        cache = cache->next;
                }
 
-               if (!reg)
-               {
-                       command_print(CMD_CTX, "%i is out of bounds, the current target has only %i registers (0 - %i)", num, count, count - 1);
+               if (!reg) {
+                       command_print(CMD_CTX, "%i is out of bounds, the current target "
+                                       "has only %i registers (0 - %i)", num, count, count - 1);
                        return ERROR_OK;
                }
-       } else /* access a single register by its name */
-       {
+       } else {
+               /* 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;
-               }
+                       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'))))
-       {
+       if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0')
+                       && (CMD_ARGV[1][0] <= '9')))) {
                if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0))
                        reg->valid = 0;
 
                if (reg->valid == 0)
-               {
                        reg->type->get(reg);
-               }
                value = buf_to_str(reg->value, reg->size, 16);
                command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value);
                free(value);
@@ -2029,9 +2904,10 @@ COMMAND_HANDLER(handle_reg_command)
        }
 
        /* set register value */
-       if (CMD_ARGC == 2)
-       {
+       if (CMD_ARGC == 2) {
                uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8));
+               if (buf == NULL)
+                       return ERROR_FAIL;
                str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0);
 
                reg->type->set(reg, buf);
@@ -2045,8 +2921,10 @@ COMMAND_HANDLER(handle_reg_command)
                return ERROR_OK;
        }
 
-       command_print(CMD_CTX, "usage: reg <#|name> [value]");
+       return ERROR_COMMAND_SYNTAX_ERROR;
 
+not_found:
+       command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]);
        return ERROR_OK;
 }
 
@@ -2055,8 +2933,7 @@ COMMAND_HANDLER(handle_poll_command)
        int retval = ERROR_OK;
        struct target *target = get_current_target(CMD_CTX);
 
-       if (CMD_ARGC == 0)
-       {
+       if (CMD_ARGC == 0) {
                command_print(CMD_CTX, "background polling: %s",
                                jtag_poll_get_enabled() ? "on" : "off");
                command_print(CMD_CTX, "TAP: %s (%s)",
@@ -2064,21 +2941,18 @@ COMMAND_HANDLER(handle_poll_command)
                                target->tap->enabled ? "enabled" : "disabled");
                if (!target->tap->enabled)
                        return ERROR_OK;
-               if ((retval = target_poll(target)) != ERROR_OK)
+               retval = target_poll(target);
+               if (retval != ERROR_OK)
                        return retval;
-               if ((retval = target_arch_state(target)) != ERROR_OK)
+               retval = target_arch_state(target);
+               if (retval != ERROR_OK)
                        return retval;
-       }
-       else if (CMD_ARGC == 1)
-       {
+       } else if (CMD_ARGC == 1) {
                bool enable;
                COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable);
                jtag_poll_set_enabled(enable);
-       }
-       else
-       {
+       } else
                return ERROR_COMMAND_SYNTAX_ERROR;
-       }
 
        return retval;
 }
@@ -2088,17 +2962,11 @@ COMMAND_HANDLER(handle_wait_halt_command)
        if (CMD_ARGC > 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       unsigned ms = 5000;
-       if (1 == CMD_ARGC)
-       {
+       unsigned ms = DEFAULT_HALT_TIMEOUT;
+       if (1 == CMD_ARGC) {
                int retval = parse_uint(CMD_ARGV[0], &ms);
                if (ERROR_OK != retval)
-               {
-                       command_print(CMD_CTX, "usage: %s [seconds]", CMD_NAME);
                        return ERROR_COMMAND_SYNTAX_ERROR;
-               }
-               // convert seconds (given) to milliseconds (needed)
-               ms *= 1000;
        }
 
        struct target *target = get_current_target(CMD_CTX);
@@ -2114,35 +2982,29 @@ COMMAND_HANDLER(handle_wait_halt_command)
 int target_wait_state(struct target *target, enum target_state state, int ms)
 {
        int retval;
-       long long then = 0, cur;
-       int once = 1;
+       int64_t then = 0, cur;
+       bool once = true;
 
-       for (;;)
-       {
-               if ((retval = target_poll(target)) != ERROR_OK)
+       for (;;) {
+               retval = target_poll(target);
+               if (retval != ERROR_OK)
                        return retval;
                if (target->state == state)
-               {
                        break;
-               }
                cur = timeval_ms();
-               if (once)
-               {
-                       once = 0;
+               if (once) {
+                       once = false;
                        then = timeval_ms();
                        LOG_DEBUG("waiting for target %s...",
-                               Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
+                               Jim_Nvp_value2name_simple(nvp_target_state, state)->name);
                }
 
                if (cur-then > 500)
-               {
                        keep_alive();
-               }
 
-               if ((cur-then) > ms)
-               {
+               if ((cur-then) > ms) {
                        LOG_ERROR("timed out while waiting for target %s",
-                               Jim_Nvp_value2name_simple(nvp_target_state,state)->name);
+                               Jim_Nvp_value2name_simple(nvp_target_state, state)->name);
                        return ERROR_FAIL;
                }
        }
@@ -2155,12 +3017,14 @@ 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;
 
-       if (CMD_ARGC == 1)
-       {
+       if (CMD_ARGC == 1) {
                unsigned wait_local;
                retval = parse_uint(CMD_ARGV[0], &wait_local);
                if (ERROR_OK != retval)
@@ -2178,7 +3042,7 @@ COMMAND_HANDLER(handle_soft_reset_halt_command)
 
        LOG_USER("requesting target halt and executing a soft reset");
 
-       target->type->soft_reset_halt(target);
+       target_soft_reset_halt(target);
 
        return ERROR_OK;
 }
@@ -2189,13 +3053,11 @@ COMMAND_HANDLER(handle_reset_command)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
        enum target_reset_mode reset_mode = RESET_RUN;
-       if (CMD_ARGC == 1)
-       {
+       if (CMD_ARGC == 1) {
                const Jim_Nvp *n;
                n = Jim_Nvp_name2value_simple(nvp_reset_modes, CMD_ARGV[0]);
-               if ((n->name == NULL) || (n->value == RESET_UNKNOWN)) {
+               if ((n->name == NULL) || (n->value == RESET_UNKNOWN))
                        return ERROR_COMMAND_SYNTAX_ERROR;
-               }
                reset_mode = n->value;
        }
 
@@ -2211,15 +3073,13 @@ COMMAND_HANDLER(handle_resume_command)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
        struct target *target = get_current_target(CMD_CTX);
-       target_handle_event(target, TARGET_EVENT_OLD_pre_resume);
 
        /* 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;
-       if (CMD_ARGC == 1)
-       {
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+       target_addr_t addr = 0;
+       if (CMD_ARGC == 1) {
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
                current = 0;
        }
 
@@ -2236,11 +3096,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);
+       if (CMD_ARGC == 1) {
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
                current_pc = 0;
        }
 
@@ -2250,7 +3109,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;
@@ -2261,38 +3120,52 @@ static void handle_md_output(struct command_context *cmd_ctx,
 
        const char *value_fmt;
        switch (size) {
-       case 4: value_fmt = "%8.8x "; break;
-       case 2: value_fmt = "%4.4x "; break;
-       case 1: value_fmt = "%2.2x "; break;
+       case 8:
+               value_fmt = "%16.16"PRIx64" ";
+               break;
+       case 4:
+               value_fmt = "%8.8"PRIx64" ";
+               break;
+       case 2:
+               value_fmt = "%4.4"PRIx64" ";
+               break;
+       case 1:
+               value_fmt = "%2.2"PRIx64" ";
+               break;
        default:
                /* "can't happen", caller checked */
                LOG_ERROR("invalid memory read size: %u", size);
                return;
        }
 
-       for (unsigned i = 0; i < count; i++)
-       {
-               if (i % line_modulo == 0)
-               {
+       for (unsigned i = 0; i < count; i++) {
+               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 4: value = target_buffer_get_u32(target, value_ptr); break;
-               case 2: value = target_buffer_get_u16(target, value_ptr); break;
-               case 1: value = *value_ptr;
+               case 8:
+                       value = target_buffer_get_u64(target, value_ptr);
+                       break;
+               case 4:
+                       value = target_buffer_get_u32(target, value_ptr);
+                       break;
+               case 2:
+                       value = target_buffer_get_u16(target, value_ptr);
+                       break;
+               case 1:
+                       value = *value_ptr;
                }
                output_len += snprintf(output + output_len,
                                sizeof(output) - output_len,
                                value_fmt, value);
 
-               if ((i % line_modulo == line_modulo - 1) || (i == count - 1))
-               {
+               if ((i % line_modulo == line_modulo - 1) || (i == count - 1)) {
                        command_print(cmd_ctx, "%s", output);
                        output_len = 0;
                }
@@ -2306,37 +3179,46 @@ COMMAND_HANDLER(handle_md_command)
 
        unsigned size = 0;
        switch (CMD_NAME[2]) {
-       case 'w': size = 4; break;
-       case 'h': size = 2; break;
-       case 'b': size = 1; break;
-       default: return ERROR_COMMAND_SYNTAX_ERROR;
+       case 'd':
+               size = 8;
+               break;
+       case 'w':
+               size = 4;
+               break;
+       case 'h':
+               size = 2;
+               break;
+       case 'b':
+               size = 1;
+               break;
+       default:
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       bool physical=strcmp(CMD_ARGV[0], "phys")==0;
+       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);
-       if (physical)
-       {
+                       target_addr_t address, uint32_t size_value, uint32_t count, uint8_t *buffer);
+       if (physical) {
                CMD_ARGC--;
                CMD_ARGV++;
-               fn=target_read_phys_memory;
+               fn = target_read_phys_memory;
        } else
-       {
-               fn=target_read_memory;
-       }
+               fn = target_read_memory;
        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);
@@ -2349,20 +3231,14 @@ COMMAND_HANDLER(handle_md_command)
 }
 
 typedef int (*target_write_fn)(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
-
-static int target_write_memory_fast(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
-{
-       return target_write_buffer(target, address, size * count, 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)
 {
@@ -2370,24 +3246,24 @@ static int target_fill_mem(struct target *target,
         * to fill large memory areas with any sane speed */
        const unsigned chunk_size = 16384;
        uint8_t *target_buf = malloc(chunk_size * data_size);
-       if (target_buf == NULL)
-       {
+       if (target_buf == NULL) {
                LOG_ERROR("Out of memory");
                return ERROR_FAIL;
        }
 
-       for (unsigned i = 0; i < chunk_size; i ++)
-       {
-               switch (data_size)
-               {
+       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);
+                       target_buffer_set_u32(target, target_buf + i * data_size, b);
                        break;
                case 2:
-                       target_buffer_set_u16(target, target_buf + i*data_size, b);
+                       target_buffer_set_u16(target, target_buf + i * data_size, b);
                        break;
                case 1:
-                       target_buffer_set_u8(target, target_buf + i*data_size, b);
+                       target_buffer_set_u8(target, target_buf + i * data_size, b);
                        break;
                default:
                        exit(-1);
@@ -2396,19 +3272,14 @@ static int target_fill_mem(struct target *target,
 
        int retval = ERROR_OK;
 
-       for (unsigned x = 0; x < c; x += chunk_size)
-       {
+       for (unsigned x = 0; x < c; x += chunk_size) {
                unsigned current;
                current = c - x;
                if (current > chunk_size)
-               {
                        current = chunk_size;
-               }
                retval = fn(target, address + x * data_size, data_size, current, target_buf);
                if (retval != ERROR_OK)
-               {
                        break;
-               }
                /* avoid GDB timeouts */
                keep_alive();
        }
@@ -2421,28 +3292,23 @@ static int target_fill_mem(struct target *target,
 COMMAND_HANDLER(handle_mw_command)
 {
        if (CMD_ARGC < 2)
-       {
                return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       bool physical=strcmp(CMD_ARGV[0], "phys")==0;
+       bool physical = strcmp(CMD_ARGV[0], "phys") == 0;
        target_write_fn fn;
-       if (physical)
-       {
+       if (physical) {
                CMD_ARGC--;
                CMD_ARGV++;
-               fn=target_write_phys_memory;
+               fn = target_write_phys_memory;
        } else
-       {
-               fn = target_write_memory_fast;
-       }
+               fn = target_write_memory;
        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)
@@ -2450,8 +3316,10 @@ COMMAND_HANDLER(handle_mw_command)
 
        struct target *target = get_current_target(CMD_CTX);
        unsigned wordsize;
-       switch (CMD_NAME[2])
-       {
+       switch (CMD_NAME[2]) {
+               case 'd':
+                       wordsize = 8;
+                       break;
                case 'w':
                        wordsize = 4;
                        break;
@@ -2469,33 +3337,28 @@ 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;
 
        /* 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);
+       if (CMD_ARGC >= 2) {
+               target_addr_t addr;
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr);
                image->base_address = addr;
                image->base_address_set = 1;
-       }
-       else
+       } else
                image->base_address_set = 0;
 
        image->start_address_set = 0;
 
        if (CMD_ARGC >= 4)
-       {
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], *min_address);
-       }
-       if (CMD_ARGC == 5)
-       {
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], *max_address);
-               // use size (given) to find max (required)
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[3], *min_address);
+       if (CMD_ARGC == 5) {
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[4], *max_address);
+               /* use size (given) to find max (required) */
                *max_address += *min_address;
        }
 
@@ -2510,8 +3373,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;
 
@@ -2526,25 +3389,22 @@ 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;
-       for (i = 0; i < image.num_sections; i++)
-       {
+       for (i = 0; i < image.num_sections; i++) {
                buffer = malloc(image.sections[i].size);
-               if (buffer == NULL)
-               {
+               if (buffer == NULL) {
                        command_print(CMD_CTX,
                                                  "error allocating buffer for section (%d bytes)",
                                                  (int)(image.sections[i].size));
+                       retval = ERROR_FAIL;
                        break;
                }
 
-               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
-               {
+               retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt);
+               if (retval != ERROR_OK) {
                        free(buffer);
                        break;
                }
@@ -2554,37 +3414,34 @@ COMMAND_HANDLER(handle_load_image_command)
 
                /* DANGER!!! beware of unsigned comparision here!!! */
 
-               if ((image.sections[i].base_address + buf_cnt >= min_address)&&
-                               (image.sections[i].base_address < max_address))
-               {
-                       if (image.sections[i].base_address < min_address)
-                       {
+               if ((image.sections[i].base_address + buf_cnt >= min_address) &&
+                               (image.sections[i].base_address < max_address)) {
+
+                       if (image.sections[i].base_address < min_address) {
                                /* clip addresses below */
                                offset += min_address-image.sections[i].base_address;
                                length -= offset;
                        }
 
                        if (image.sections[i].base_address + buf_cnt > max_address)
-                       {
                                length -= (image.sections[i].base_address + buf_cnt)-max_address;
-                       }
 
-                       if ((retval = target_write_buffer(target, image.sections[i].base_address + offset, length, buffer + offset)) != ERROR_OK)
-                       {
+                       retval = target_write_buffer(target,
+                                       image.sections[i].base_address + offset, length, buffer + offset);
+                       if (retval != ERROR_OK) {
                                free(buffer);
                                break;
                        }
                        image_size += length;
-                       command_print(CMD_CTX, "%u bytes written at address 0x%8.8" PRIx32 "",
-                                                 (unsigned int)length,
-                                                 image.sections[i].base_address + offset);
+                       command_print(CMD_CTX, "%u bytes written at address " TARGET_ADDR_FMT "",
+                                       (unsigned int)length,
+                                       image.sections[i].base_address + offset);
                }
 
                free(buffer);
        }
 
-       if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
-       {
+       if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
                command_print(CMD_CTX, "downloaded %" PRIu32 " bytes "
                                "in %fs (%0.3f KiB/s)", image_size,
                                duration_elapsed(&bench), duration_kbps(&bench, image_size));
@@ -2598,64 +3455,73 @@ COMMAND_HANDLER(handle_load_image_command)
 
 COMMAND_HANDLER(handle_dump_image_command)
 {
-       struct fileio fileio;
-       uint8_t buffer[560];
+       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);
+       if (!buffer)
+               return ERROR_FAIL;
 
        retval = fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY);
-       if (retval != ERROR_OK)
+       if (retval != ERROR_OK) {
+               free(buffer);
                return retval;
+       }
 
        duration_start(&bench);
 
-       retval = ERROR_OK;
-       while (size > 0)
-       {
+       while (size > 0) {
                size_t size_written;
-               uint32_t this_run_size = (size > 560) ? 560 : size;
+               uint32_t this_run_size = (size > buf_size) ? buf_size : size;
                retval = target_read_buffer(target, address, this_run_size, buffer);
                if (retval != ERROR_OK)
-               {
                        break;
-               }
 
-               retval = fileio_write(&fileio, this_run_size, buffer, &size_written);
+               retval = fileio_write(fileio, this_run_size, buffer, &size_written);
                if (retval != ERROR_OK)
-               {
                        break;
-               }
 
                size -= this_run_size;
                address += this_run_size;
        }
 
-       if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
-       {
-               int filesize;
-               retval = fileio_size(&fileio, &filesize);
+       free(buffer);
+
+       if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
+               size_t filesize;
+               retval = fileio_size(fileio, &filesize);
                if (retval != ERROR_OK)
                        return retval;
                command_print(CMD_CTX,
-                               "dumped %ld bytes in %fs (%0.3f KiB/s)", (long)filesize,
+                               "dumped %zu bytes in %fs (%0.3f KiB/s)", filesize,
                                duration_elapsed(&bench), duration_kbps(&bench, filesize));
        }
 
-       if ((retvaltemp = fileio_close(&fileio)) != ERROR_OK)
+       retvaltemp = fileio_close(fileio);
+       if (retvaltemp != ERROR_OK)
                return retvaltemp;
 
        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;
@@ -2670,12 +3536,9 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
        struct target *target = get_current_target(CMD_CTX);
 
        if (CMD_ARGC < 1)
-       {
                return ERROR_COMMAND_SYNTAX_ERROR;
-       }
 
-       if (!target)
-       {
+       if (!target) {
                LOG_ERROR("no target selected");
                return ERROR_FAIL;
        }
@@ -2683,98 +3546,86 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
        struct duration bench;
        duration_start(&bench);
 
-       if (CMD_ARGC >= 2)
-       {
-               uint32_t addr;
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
+       if (CMD_ARGC >= 2) {
+               target_addr_t addr;
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr);
                image.base_address = addr;
                image.base_address_set = 1;
-       }
-       else
-       {
+       } else {
                image.base_address_set = 0;
                image.base_address = 0x0;
        }
 
        image.start_address_set = 0;
 
-       if ((retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL)) != ERROR_OK)
-       {
+       retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL);
+       if (retval != ERROR_OK)
                return retval;
-       }
 
        image_size = 0x0;
        int diffs = 0;
        retval = ERROR_OK;
-       for (i = 0; i < image.num_sections; i++)
-       {
+       for (i = 0; i < image.num_sections; i++) {
                buffer = malloc(image.sections[i].size);
-               if (buffer == NULL)
-               {
+               if (buffer == NULL) {
                        command_print(CMD_CTX,
-                                                 "error allocating buffer for section (%d bytes)",
-                                                 (int)(image.sections[i].size));
+                                       "error allocating buffer for section (%d bytes)",
+                                       (int)(image.sections[i].size));
                        break;
                }
-               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
-               {
+               retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt);
+               if (retval != ERROR_OK) {
                        free(buffer);
                        break;
                }
 
-               if (verify)
-               {
+               if (verify >= IMAGE_VERIFY) {
                        /* calculate checksum of image */
                        retval = image_calculate_checksum(buffer, buf_cnt, &checksum);
-                       if (retval != ERROR_OK)
-                       {
+                       if (retval != ERROR_OK) {
                                free(buffer);
                                break;
                        }
 
                        retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
-                       if (retval != ERROR_OK)
-                       {
+                       if (retval != ERROR_OK) {
                                free(buffer);
                                break;
                        }
-
-                       if (checksum != mem_checksum)
-                       {
+                       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;
 
                                if (diffs == 0)
-                               {
                                        LOG_ERROR("checksum mismatch - attempting binary compare");
-                               }
 
-                               data = (uint8_t*)malloc(buf_cnt);
+                               data = malloc(buf_cnt);
 
                                /* Can we use 32bit word accesses? */
                                int size = 1;
                                int count = buf_cnt;
-                               if ((count % 4) == 0)
-                               {
+                               if ((count % 4) == 0) {
                                        size *= 4;
                                        count /= 4;
                                }
                                retval = target_read_memory(target, image.sections[i].base_address, size, count, data);
-                               if (retval == ERROR_OK)
-                               {
+                               if (retval == ERROR_OK) {
                                        uint32_t t;
-                                       for (t = 0; t < buf_cnt; t++)
-                                       {
-                                               if (data[t] != buffer[t])
-                                               {
+                                       for (t = 0; t < buf_cnt; t++) {
+                                               if (data[t] != buffer[t]) {
                                                        command_print(CMD_CTX,
                                                                                  "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x",
                                                                                  diffs,
                                                                                  (unsigned)(t + image.sections[i].base_address),
                                                                                  data[t],
                                                                                  buffer[t]);
-                                                       if (diffs++ >= 127)
-                                                       {
+                                                       if (diffs++ >= 127) {
                                                                command_print(CMD_CTX, "More than 128 errors, the rest are not printed.");
                                                                free(data);
                                                                free(buffer);
@@ -2786,9 +3637,8 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
                                }
                                free(data);
                        }
-               } else
-               {
-                       command_print(CMD_CTX, "address 0x%08" PRIx32 " length 0x%08zx",
+               } else {
+                       command_print(CMD_CTX, "address " TARGET_ADDR_FMT " length 0x%08zx",
                                                  image.sections[i].base_address,
                                                  buf_cnt);
                }
@@ -2797,16 +3647,11 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
                image_size += buf_cnt;
        }
        if (diffs > 0)
-       {
                command_print(CMD_CTX, "No more differences found.");
-       }
 done:
        if (diffs > 0)
-       {
                retval = ERROR_FAIL;
-       }
-       if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
-       {
+       if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
                command_print(CMD_CTX, "verified %" PRIu32 " bytes "
                                "in %fs (%0.3f KiB/s)", image_size,
                                duration_elapsed(&bench), duration_kbps(&bench, image_size));
@@ -2817,37 +3662,49 @@ 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)
 {
        struct target *target = get_current_target(cmd_ctx);
        struct breakpoint *breakpoint = target->breakpoints;
-       while (breakpoint)
-       {
-               if (breakpoint->type == BKPT_SOFT)
-               {
-                       char* buf = buf_to_str(breakpoint->orig_instr,
+       while (breakpoint) {
+               if (breakpoint->type == BKPT_SOFT) {
+                       char *buf = buf_to_str(breakpoint->orig_instr,
                                        breakpoint->length, 16);
-                       command_print(cmd_ctx, "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);
                        free(buf);
-               }
-               else
-               {
-                       command_print(cmd_ctx, "0x%8.8" PRIx32 ", 0x%x, %i",
-                                                 breakpoint->address,
-                                                 breakpoint->length, breakpoint->set);
+               } else {
+                       if ((breakpoint->address == 0) && (breakpoint->asid != 0))
+                               command_print(cmd_ctx, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i",
+                                                       breakpoint->asid,
+                                                       breakpoint->length, breakpoint->set);
+                       else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) {
+                               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): " TARGET_ADDR_FMT ", 0x%x, %i",
+                                                       breakpoint->address,
+                                                       breakpoint->length, breakpoint->set);
                }
 
                breakpoint = breakpoint->next;
@@ -2856,43 +3713,82 @@ 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 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 = breakpoint_add(target, addr, length, hw);
-       if (ERROR_OK == retval)
-               command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr);
-       else
-               LOG_ERROR("Failure setting breakpoint");
+       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 " TARGET_ADDR_FMT "", addr);
+
+       } else if (addr == 0) {
+               if (target->type->add_context_breakpoint == NULL) {
+                       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 {
+               if (target->type->add_hybrid_breakpoint == NULL) {
+                       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);
+       }
        return retval;
 }
 
 COMMAND_HANDLER(handle_bp_command)
 {
-       if (CMD_ARGC == 0)
-               return handle_bp_command_list(CMD_CTX);
-
-       if (CMD_ARGC < 2 || CMD_ARGC > 3)
-       {
-               command_print(CMD_CTX, "usage: bp <address> <length> ['hw']");
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
-       uint32_t addr;
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+       target_addr_t addr;
+       uint32_t asid;
        uint32_t length;
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
-
        int hw = BKPT_SOFT;
-       if (CMD_ARGC == 3)
-       {
-               if (strcmp(CMD_ARGV[2], "hw") == 0)
+
+       switch (CMD_ARGC) {
+               case 0:
+                       return handle_bp_command_list(CMD_CTX);
+
+               case 2:
+                       asid = 0;
+                       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_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) {
+                               hw = BKPT_HARD;
+                               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], asid);
+                               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
+                               addr = 0;
+                               return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
+                       }
+                       /* fallthrough */
+               case 4:
                        hw = BKPT_HARD;
-               else
+                       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);
+
+               default:
                        return ERROR_COMMAND_SYNTAX_ERROR;
        }
-
-       return handle_bp_command_set(CMD_CTX, addr, length, hw);
 }
 
 COMMAND_HANDLER(handle_rbp_command)
@@ -2900,8 +3796,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);
@@ -2913,13 +3809,11 @@ COMMAND_HANDLER(handle_wp_command)
 {
        struct target *target = get_current_target(CMD_CTX);
 
-       if (CMD_ARGC == 0)
-       {
+       if (CMD_ARGC == 0) {
                struct watchpoint *watchpoint = target->watchpoints;
 
-               while (watchpoint)
-               {
-                       command_print(CMD_CTX, "address: 0x%8.8" PRIx32
+               while (watchpoint) {
+                       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,
@@ -2939,17 +3833,15 @@ COMMAND_HANDLER(handle_wp_command)
        uint32_t data_value = 0x0;
        uint32_t data_mask = 0xffffffff;
 
-       switch (CMD_ARGC)
-       {
+       switch (CMD_ARGC) {
        case 5:
                COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], data_mask);
-               // fall through
+               /* fall through */
        case 4:
                COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], data_value);
-               // fall through
+               /* fall through */
        case 3:
-               switch (CMD_ARGV[2][0])
-               {
+               switch (CMD_ARGV[2][0]) {
                case 'r':
                        type = WPT_READ;
                        break;
@@ -2963,15 +3855,13 @@ COMMAND_HANDLER(handle_wp_command)
                        LOG_ERROR("invalid watchpoint mode ('%c')", CMD_ARGV[2][0]);
                        return ERROR_COMMAND_SYNTAX_ERROR;
                }
-               // fall through
+               /* fall through */
        case 2:
                COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
                COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
                break;
 
        default:
-               command_print(CMD_CTX, "usage: wp [address length "
-                               "[(r|w|a) [value [mask]]]]");
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
@@ -2997,7 +3887,6 @@ COMMAND_HANDLER(handle_rwp_command)
        return ERROR_OK;
 }
 
-
 /**
  * Translate a virtual address to a physical address.
  *
@@ -3009,14 +3898,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;
 }
@@ -3028,15 +3917,12 @@ static void writeData(FILE *f, const void *data, size_t len)
                LOG_ERROR("failed to write %zu bytes: %s", len, strerror(errno));
 }
 
-static void writeLong(FILE *f, int l)
+static void writeLong(FILE *f, int l, struct target *target)
 {
-       int i;
-       for (i = 0; i < 4; i++)
-       {
-               char c = (l >> (i*8))&0xff;
-               writeData(f, &c, 1);
-       }
+       uint8_t val[4];
 
+       target_buffer_set_u32(target, val, l);
+       writeData(f, val, 4);
 }
 
 static void writeString(FILE *f, char *s)
@@ -3044,67 +3930,80 @@ static void writeString(FILE *f, char *s)
        writeData(f, s, strlen(s));
 }
 
+typedef unsigned char UNIT[2];  /* unit of profiling */
+
 /* Dump a gmon.out histogram file. */
-static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filename)
+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 duration_ms)
 {
        uint32_t i;
        FILE *f = fopen(filename, "w");
        if (f == NULL)
                return;
        writeString(f, "gmon");
-       writeLong(f, 0x00000001); /* Version */
-       writeLong(f, 0); /* padding */
-       writeLong(f, 0); /* padding */
-       writeLong(f, 0); /* padding */
+       writeLong(f, 0x00000001, target); /* Version */
+       writeLong(f, 0, target); /* padding */
+       writeLong(f, 0, target); /* padding */
+       writeLong(f, 0, target); /* padding */
 
        uint8_t zero = 0;  /* GMON_TAG_TIME_HIST */
        writeData(f, &zero, 1);
 
        /* figure out bucket size */
-       uint32_t min = samples[0];
-       uint32_t max = samples[0];
-       for (i = 0; i < sampleNum; i++)
-       {
-               if (min > samples[i])
-               {
-                       min = samples[i];
-               }
-               if (max < samples[i])
-               {
-                       max = samples[i];
+       uint32_t min;
+       uint32_t max;
+       if (with_range) {
+               min = start_address;
+               max = end_address;
+       } else {
+               min = samples[0];
+               max = samples[0];
+               for (i = 0; i < sampleNum; i++) {
+                       if (min > samples[i])
+                               min = samples[i];
+                       if (max < samples[i])
+                               max = samples[i];
                }
+
+               /* max should be (largest sample + 1)
+                * Refer to binutils/gprof/hist.c (find_histogram_for_pc) */
+               max++;
        }
 
-       int addressSpace = (max-min + 1);
+       int addressSpace = max - min;
+       assert(addressSpace >= 2);
 
-       static const uint32_t maxBuckets = 16 * 1024; /* maximum buckets. */
-       uint32_t length = addressSpace;
-       if (length > maxBuckets)
-       {
-               length = maxBuckets;
-       }
-       int *buckets = malloc(sizeof(int)*length);
-       if (buckets == NULL)
-       {
+       /* FIXME: What is the reasonable number of buckets?
+        * The profiling result will be more accurate if there are enough buckets. */
+       static const uint32_t maxBuckets = 128 * 1024; /* maximum buckets. */
+       uint32_t numBuckets = addressSpace / sizeof(UNIT);
+       if (numBuckets > maxBuckets)
+               numBuckets = maxBuckets;
+       int *buckets = malloc(sizeof(int) * numBuckets);
+       if (buckets == NULL) {
                fclose(f);
                return;
        }
-       memset(buckets, 0, sizeof(int)*length);
-       for (i = 0; i < sampleNum;i++)
-       {
+       memset(buckets, 0, sizeof(int) * numBuckets);
+       for (i = 0; i < sampleNum; i++) {
                uint32_t address = samples[i];
-               long long a = address-min;
-               long long b = length-1;
-               long long c = addressSpace-1;
-               int index_t = (a*b)/c; /* danger!!!! int32 overflows */
+
+               if ((address < min) || (max <= address))
+                       continue;
+
+               long long a = address - min;
+               long long b = numBuckets;
+               long long c = addressSpace;
+               int index_t = (a * b) / c; /* danger!!!! int32 overflows */
                buckets[index_t]++;
        }
 
        /* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */
-       writeLong(f, min);                      /* low_pc */
-       writeLong(f, max);                      /* high_pc */
-       writeLong(f, length);           /* # of samples */
-       writeLong(f, 100);                      /* KLUDGE! We lie, ca. 100Hz best case. */
+       writeLong(f, min, target);                      /* low_pc */
+       writeLong(f, max, target);                      /* high_pc */
+       writeLong(f, numBuckets, target);       /* # of buckets */
+       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);
@@ -3112,27 +4011,21 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filenam
 
        /*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */
 
-       char *data = malloc(2*length);
-       if (data != NULL)
-       {
-               for (i = 0; i < length;i++)
-               {
+       char *data = malloc(2 * numBuckets);
+       if (data != NULL) {
+               for (i = 0; i < numBuckets; i++) {
                        int val;
                        val = buckets[i];
                        if (val > 65535)
-                       {
                                val = 65535;
-                       }
-                       data[i*2]=val&0xff;
-                       data[i*2 + 1]=(val >> 8)&0xff;
+                       data[i * 2] = val&0xff;
+                       data[i * 2 + 1] = (val >> 8) & 0xff;
                }
                free(buckets);
-               writeData(f, data, length * 2);
+               writeData(f, data, numBuckets * 2);
                free(data);
        } else
-       {
                free(buckets);
-       }
 
        fclose(f);
 }
@@ -3142,94 +4035,76 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filenam
 COMMAND_HANDLER(handle_profile_command)
 {
        struct target *target = get_current_target(CMD_CTX);
-       struct timeval timeout, now;
 
-       gettimeofday(&timeout, NULL);
-       if (CMD_ARGC != 2)
-       {
+       if ((CMD_ARGC != 2) && (CMD_ARGC != 4))
                return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       unsigned offset;
-       COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], offset);
 
-       timeval_add_time(&timeout, offset, 0);
+       const uint32_t MAX_PROFILE_SAMPLE_NUM = 10000;
+       uint32_t offset;
+       uint32_t num_of_samples;
+       int retval = ERROR_OK;
+
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], offset);
+
+       uint32_t *samples = malloc(sizeof(uint32_t) * MAX_PROFILE_SAMPLE_NUM);
+       if (samples == NULL) {
+               LOG_ERROR("No memory to store samples.");
+               return ERROR_FAIL;
+       }
 
+       uint64_t timestart_ms = timeval_ms();
        /**
-        * @todo: Some cores let us sample the PC without the
+        * Some cores let us sample the PC without the
         * annoying halt/resume step; for example, ARMv7 PCSR.
         * Provide a way to use that more efficient mechanism.
         */
+       retval = target_profiling(target, samples, MAX_PROFILE_SAMPLE_NUM,
+                               &num_of_samples, offset);
+       if (retval != ERROR_OK) {
+               free(samples);
+               return retval;
+       }
+       uint32_t duration_ms = timeval_ms() - timestart_ms;
 
-       command_print(CMD_CTX, "Starting profiling. Halting and resuming the target as often as we can...");
-
-       static const int maxSample = 10000;
-       uint32_t *samples = malloc(sizeof(uint32_t)*maxSample);
-       if (samples == NULL)
-               return ERROR_OK;
-
-       int numSamples = 0;
-       /* hopefully it is safe to cache! We want to stop/restart as quickly as possible. */
-       struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1);
+       assert(num_of_samples <= MAX_PROFILE_SAMPLE_NUM);
 
-       for (;;)
-       {
-               int retval;
-               target_poll(target);
-               if (target->state == TARGET_HALTED)
-               {
-                       uint32_t t=*((uint32_t *)reg->value);
-                       samples[numSamples++]=t;
-                       retval = target_resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */
-                       target_poll(target);
-                       alive_sleep(10); /* sleep 10ms, i.e. <100 samples/second. */
-               } else if (target->state == TARGET_RUNNING)
-               {
-                       /* We want to quickly sample the PC. */
-                       if ((retval = target_halt(target)) != ERROR_OK)
-                       {
-                               free(samples);
-                               return retval;
-                       }
-               } else
-               {
-                       command_print(CMD_CTX, "Target not halted or running");
-                       retval = ERROR_OK;
-                       break;
-               }
-               if (retval != ERROR_OK)
-               {
-                       break;
+       retval = target_poll(target);
+       if (retval != ERROR_OK) {
+               free(samples);
+               return retval;
+       }
+       if (target->state == TARGET_RUNNING) {
+               retval = target_halt(target);
+               if (retval != ERROR_OK) {
+                       free(samples);
+                       return retval;
                }
+       }
 
-               gettimeofday(&now, NULL);
-               if ((numSamples >= maxSample) || ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
-               {
-                       command_print(CMD_CTX, "Profiling completed. %d samples.", numSamples);
-                       if ((retval = target_poll(target)) != ERROR_OK)
-                       {
-                               free(samples);
-                               return retval;
-                       }
-                       if (target->state == TARGET_HALTED)
-                       {
-                               target_resume(target, 1, 0, 0, 0); /* current pc, addr = 0, do not handle breakpoints, not debugging */
-                       }
-                       if ((retval = target_poll(target)) != ERROR_OK)
-                       {
-                               free(samples);
-                               return retval;
-                       }
-                       writeGmon(samples, numSamples, CMD_ARGV[1]);
-                       command_print(CMD_CTX, "Wrote %s", CMD_ARGV[1]);
-                       break;
-               }
+       retval = target_poll(target);
+       if (retval != ERROR_OK) {
+               free(samples);
+               return retval;
        }
-       free(samples);
 
-       return ERROR_OK;
+       uint32_t start_address = 0;
+       uint32_t end_address = 0;
+       bool with_range = false;
+       if (CMD_ARGC == 4) {
+               with_range = true;
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], start_address);
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], end_address);
+       }
+
+       write_gmon(samples, num_of_samples, CMD_ARGV[1],
+                  with_range, start_address, end_address, target, duration_ms);
+       command_print(CMD_CTX, "Wrote %s", CMD_ARGV[1]);
+
+       free(samples);
+       return retval;
 }
 
-static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, uint32_t val)
+static int new_int_array_element(Jim_Interp *interp, const char *varname, int idx, uint32_t val)
 {
        char *namebuf;
        Jim_Obj *nameObjPtr, *valObjPtr;
@@ -3241,8 +4116,7 @@ static int new_int_array_element(Jim_Interp * interp, const char *varname, int i
 
        nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
        valObjPtr = Jim_NewIntObj(interp, val);
-       if (!nameObjPtr || !valObjPtr)
-       {
+       if (!nameObjPtr || !valObjPtr) {
                free(namebuf);
                return JIM_ERR;
        }
@@ -3263,16 +4137,15 @@ static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        struct target *target;
 
        context = current_command_context(interp);
-       assert (context != NULL);
+       assert(context != NULL);
 
        target = get_current_target(context);
-       if (target == NULL)
-       {
+       if (target == NULL) {
                LOG_ERROR("mem2array: no current target");
                return JIM_ERR;
        }
 
-       return  target_mem2array(interp, target, argc-1, argv + 1);
+       return target_mem2array(interp, target, argc - 1, argv + 1);
 }
 
 static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv)
@@ -3284,6 +4157,8 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc,
        uint32_t count;
        uint32_t v;
        const char *varname;
+       const char *phys;
+       bool is_phys;
        int  n, e, retval;
        uint32_t i;
 
@@ -3292,8 +4167,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) {
-               Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems");
+
+       if (argc < 4 || argc > 5) {
+               Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]");
                return JIM_ERR;
        }
        varname = Jim_GetString(argv[0], &len);
@@ -3301,19 +4177,24 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc,
 
        e = Jim_GetLong(interp, argv[1], &l);
        width = l;
-       if (e != JIM_OK) {
+       if (e != JIM_OK)
                return e;
-       }
 
        e = Jim_GetLong(interp, argv[2], &l);
        addr = l;
-       if (e != JIM_OK) {
+       if (e != JIM_OK)
                return e;
-       }
        e = Jim_GetLong(interp, argv[3], &l);
        len = l;
-       if (e != JIM_OK) {
+       if (e != JIM_OK)
                return e;
+       is_phys = false;
+       if (argc > 4) {
+               phys = Jim_GetString(argv[4], &n);
+               if (!strncmp(phys, "phys", n))
+                       is_phys = true;
+               else
+                       return JIM_ERR;
        }
        switch (width) {
                case 8:
@@ -3357,7 +4238,7 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc,
                sprintf(buf, "mem2array address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads",
                                addr,
                                width);
-               Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
+               Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL);
                return JIM_ERR;
        }
 
@@ -3377,24 +4258,26 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc,
                /* Slurp... in buffer size chunks */
 
                count = len; /* in objects.. */
-               if (count > (buffersize/width)) {
-                       count = (buffersize/width);
-               }
+               if (count > (buffersize / width))
+                       count = (buffersize / width);
 
-               retval = target_read_memory(target, addr, width, count, buffer);
+               if (is_phys)
+                       retval = target_read_phys_memory(target, addr, width, count, buffer);
+               else
+                       retval = target_read_memory(target, addr, width, count, buffer);
                if (retval != ERROR_OK) {
                        /* BOO !*/
-                       LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed",
-                                         (unsigned int)addr,
-                                         (int)width,
-                                         (int)count);
+                       LOG_ERROR("mem2array: Read @ 0x%08" PRIx32 ", w=%" PRId32 ", cnt=%" PRId32 ", failed",
+                                         addr,
+                                         width,
+                                         count);
                        Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
                        Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL);
                        e = JIM_ERR;
-                       len = 0;
+                       break;
                } else {
                        v = 0; /* shut up gcc */
-                       for (i = 0 ;i < count ;i++, n++) {
+                       for (i = 0; i < count ; i++, n++) {
                                switch (width) {
                                        case 4:
                                                v = target_buffer_get_u32(target, &buffer[i*width]);
@@ -3409,6 +4292,7 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc,
                                new_int_array_element(interp, varname, n, v);
                        }
                        len -= count;
+                       addr += count * width;
                }
        }
 
@@ -3416,10 +4300,10 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc,
 
        Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
 
-       return JIM_OK;
+       return e;
 }
 
-static int get_int_array_element(Jim_Interp * interp, const char *varname, int idx, uint32_t *val)
+static int get_int_array_element(Jim_Interp *interp, const char *varname, int idx, uint32_t *val)
 {
        char *namebuf;
        Jim_Obj *nameObjPtr, *valObjPtr;
@@ -3431,8 +4315,7 @@ static int get_int_array_element(Jim_Interp * interp, const char *varname, int i
                return JIM_ERR;
 
        nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
-       if (!nameObjPtr)
-       {
+       if (!nameObjPtr) {
                free(namebuf);
                return JIM_ERR;
        }
@@ -3456,7 +4339,7 @@ static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        struct target *target;
 
        context = current_command_context(interp);
-       assert (context != NULL);
+       assert(context != NULL);
 
        target = get_current_target(context);
        if (target == NULL) {
@@ -3464,7 +4347,7 @@ static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
                return JIM_ERR;
        }
 
-       return target_array2mem(interp,target, argc-1, argv + 1);
+       return target_array2mem(interp, target, argc-1, argv + 1);
 }
 
 static int target_array2mem(Jim_Interp *interp, struct target *target,
@@ -3477,6 +4360,8 @@ static int target_array2mem(Jim_Interp *interp, struct target *target,
        uint32_t count;
        uint32_t v;
        const char *varname;
+       const char *phys;
+       bool is_phys;
        int  n, e, retval;
        uint32_t i;
 
@@ -3485,8 +4370,8 @@ static int target_array2mem(Jim_Interp *interp, struct target *target,
         * argv[3] = memory address
         * argv[4] = count to write
         */
-       if (argc != 4) {
-               Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems");
+       if (argc < 4 || argc > 5) {
+               Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]");
                return JIM_ERR;
        }
        varname = Jim_GetString(argv[0], &len);
@@ -3494,19 +4379,24 @@ static int target_array2mem(Jim_Interp *interp, struct target *target,
 
        e = Jim_GetLong(interp, argv[1], &l);
        width = l;
-       if (e != JIM_OK) {
+       if (e != JIM_OK)
                return e;
-       }
 
        e = Jim_GetLong(interp, argv[2], &l);
        addr = l;
-       if (e != JIM_OK) {
+       if (e != JIM_OK)
                return e;
-       }
        e = Jim_GetLong(interp, argv[3], &l);
        len = l;
-       if (e != JIM_OK) {
+       if (e != JIM_OK)
                return e;
+       is_phys = false;
+       if (argc > 4) {
+               phys = Jim_GetString(argv[4], &n);
+               if (!strncmp(phys, "phys", n))
+                       is_phys = true;
+               else
+                       return JIM_ERR;
        }
        switch (width) {
                case 8:
@@ -3520,23 +4410,27 @@ static int target_array2mem(Jim_Interp *interp, struct target *target,
                        break;
                default:
                        Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
-                       Jim_AppendStrings(interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL);
+                       Jim_AppendStrings(interp, Jim_GetResult(interp),
+                                       "Invalid width param, must be 8/16/32", NULL);
                        return JIM_ERR;
        }
        if (len == 0) {
                Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
-               Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: zero width read?", NULL);
+               Jim_AppendStrings(interp, Jim_GetResult(interp),
+                               "array2mem: zero width read?", NULL);
                return JIM_ERR;
        }
        if ((addr + (len * width)) < addr) {
                Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
-               Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: addr + len - wraps to zero?", NULL);
+               Jim_AppendStrings(interp, Jim_GetResult(interp),
+                               "array2mem: addr + len - wraps to zero?", NULL);
                return JIM_ERR;
        }
        /* absurd transfer size? */
        if (len > 65536) {
                Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
-               Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: absurd > 64K item request", NULL);
+               Jim_AppendStrings(interp, Jim_GetResult(interp),
+                               "array2mem: absurd > 64K item request", NULL);
                return JIM_ERR;
        }
 
@@ -3547,10 +4441,10 @@ static int target_array2mem(Jim_Interp *interp, struct target *target,
        } else {
                char buf[100];
                Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
-               sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads",
-                               (unsigned int)addr,
-                               (int)width);
-               Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL);
+               sprintf(buf, "array2mem address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads",
+                               addr,
+                               width);
+               Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL);
                return JIM_ERR;
        }
 
@@ -3570,19 +4464,18 @@ static int target_array2mem(Jim_Interp *interp, struct target *target,
                /* Slurp... in buffer size chunks */
 
                count = len; /* in objects.. */
-               if (count > (buffersize/width)) {
-                       count = (buffersize/width);
-               }
+               if (count > (buffersize / width))
+                       count = (buffersize / width);
 
                v = 0; /* shut up gcc */
-               for (i = 0 ;i < count ;i++, n++) {
+               for (i = 0; i < count; i++, n++) {
                        get_int_array_element(interp, varname, n, &v);
                        switch (width) {
                        case 4:
-                               target_buffer_set_u32(target, &buffer[i*width], v);
+                               target_buffer_set_u32(target, &buffer[i * width], v);
                                break;
                        case 2:
-                               target_buffer_set_u16(target, &buffer[i*width], v);
+                               target_buffer_set_u16(target, &buffer[i * width], v);
                                break;
                        case 1:
                                buffer[i] = v & 0x0ff;
@@ -3591,25 +4484,29 @@ static int target_array2mem(Jim_Interp *interp, struct target *target,
                }
                len -= count;
 
-               retval = target_write_memory(target, addr, width, count, buffer);
+               if (is_phys)
+                       retval = target_write_phys_memory(target, addr, width, count, buffer);
+               else
+                       retval = target_write_memory(target, addr, width, count, buffer);
                if (retval != ERROR_OK) {
                        /* BOO !*/
-                       LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed",
-                                         (unsigned int)addr,
-                                         (int)width,
-                                         (int)count);
+                       LOG_ERROR("array2mem: Write @ 0x%08" PRIx32 ", w=%" PRId32 ", cnt=%" PRId32 ", failed",
+                                         addr,
+                                         width,
+                                         count);
                        Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
                        Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL);
                        e = JIM_ERR;
-                       len = 0;
+                       break;
                }
+               addr += count * width;
        }
 
        free(buffer);
 
        Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
 
-       return JIM_OK;
+       return e;
 }
 
 /* FIX? should we propagate errors here rather than printing them
@@ -3621,18 +4518,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));
-                       if (Jim_EvalObj(teap->interp, teap->body) != JIM_OK)
-                       {
+
+                       /* 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));
+                               command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(teap->interp), NULL));
                        }
+
+                       cmd_ctx->current_target_override = saved_target_override;
                }
        }
 }
@@ -3659,9 +4566,12 @@ enum target_cfg_param {
        TCFG_WORK_AREA_SIZE,
        TCFG_WORK_AREA_BACKUP,
        TCFG_ENDIAN,
-       TCFG_VARIANT,
        TCFG_COREID,
        TCFG_CHAIN_POSITION,
+       TCFG_DBGBASE,
+       TCFG_RTOS,
+       TCFG_DEFER_EXAMINE,
+       TCFG_GDB_PORT,
 };
 
 static Jim_Nvp nvp_config_opts[] = {
@@ -3672,10 +4582,12 @@ static Jim_Nvp nvp_config_opts[] = {
        { .name = "-work-area-size",   .value = TCFG_WORK_AREA_SIZE },
        { .name = "-work-area-backup", .value = TCFG_WORK_AREA_BACKUP },
        { .name = "-endian" ,          .value = TCFG_ENDIAN },
-       { .name = "-variant",          .value = TCFG_VARIANT },
        { .name = "-coreid",           .value = TCFG_COREID },
        { .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 }
 };
 
@@ -3684,7 +4596,6 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
        Jim_Nvp *n;
        Jim_Obj *o;
        jim_wide w;
-       char *cp;
        int e;
 
        /* parse config or cget options ... */
@@ -3719,7 +4630,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                                                "not settable: %s", n->name);
                                return JIM_ERR;
                        } else {
-                       no_params:
+no_params:
                                if (goi->argc != 0) {
                                        Jim_WrongNumArgs(goi->interp,
                                                        goi->argc, goi->argv,
@@ -3761,9 +4672,8 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                                teap = target->event_action;
                                /* replace existing? */
                                while (teap) {
-                                       if (teap->event == (enum target_event)n->value) {
+                                       if (teap->event == (enum target_event)n->value)
                                                break;
-                                       }
                                        teap = teap->next;
                                }
 
@@ -3777,9 +4687,8 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                                        teap->event = n->value;
                                        teap->interp = goi->interp;
                                        Jim_GetOpt_Obj(goi, &o);
-                                       if (teap->body) {
+                                       if (teap->body)
                                                Jim_DecrRefCount(teap->interp, teap->body);
-                                       }
                                        teap->body  = Jim_DuplicateObj(goi->interp, o);
                                        /*
                                         * FIXME:
@@ -3793,8 +4702,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                                         */
                                        Jim_IncrRefCount(teap->body);
 
-                                       if (!replace)
-                                       {
+                                       if (!replace) {
                                                /* add to head of event list */
                                                teap->next = target->event_action;
                                                target->event_action = teap;
@@ -3802,11 +4710,10 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                                        Jim_SetEmptyResult(goi->interp);
                                } else {
                                        /* get */
-                                       if (teap == NULL) {
+                                       if (teap == NULL)
                                                Jim_SetEmptyResult(goi->interp);
-                                       } else {
+                                       else
                                                Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, teap->body));
-                                       }
                                }
                        }
                        /* loop for more */
@@ -3816,15 +4723,13 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                        if (goi->isconfigure) {
                                target_free_all_working_areas(target);
                                e = Jim_GetOpt_Wide(goi, &w);
-                               if (e != JIM_OK) {
+                               if (e != JIM_OK)
                                        return e;
-                               }
                                target->working_area_virt = w;
                                target->working_area_virt_spec = true;
                        } else {
-                               if (goi->argc != 0) {
+                               if (goi->argc != 0)
                                        goto no_params;
-                               }
                        }
                        Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_virt));
                        /* loop for more */
@@ -3834,15 +4739,13 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                        if (goi->isconfigure) {
                                target_free_all_working_areas(target);
                                e = Jim_GetOpt_Wide(goi, &w);
-                               if (e != JIM_OK) {
+                               if (e != JIM_OK)
                                        return e;
-                               }
                                target->working_area_phys = w;
                                target->working_area_phys_spec = true;
                        } else {
-                               if (goi->argc != 0) {
+                               if (goi->argc != 0)
                                        goto no_params;
-                               }
                        }
                        Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_phys));
                        /* loop for more */
@@ -3852,14 +4755,12 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                        if (goi->isconfigure) {
                                target_free_all_working_areas(target);
                                e = Jim_GetOpt_Wide(goi, &w);
-                               if (e != JIM_OK) {
+                               if (e != JIM_OK)
                                        return e;
-                               }
                                target->working_area_size = w;
                        } else {
-                               if (goi->argc != 0) {
+                               if (goi->argc != 0)
                                        goto no_params;
-                               }
                        }
                        Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size));
                        /* loop for more */
@@ -3869,20 +4770,19 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                        if (goi->isconfigure) {
                                target_free_all_working_areas(target);
                                e = Jim_GetOpt_Wide(goi, &w);
-                               if (e != JIM_OK) {
+                               if (e != JIM_OK)
                                        return e;
-                               }
                                /* make this exactly 1 or 0 */
                                target->backup_working_area = (!!w);
                        } else {
-                               if (goi->argc != 0) {
+                               if (goi->argc != 0)
                                        goto no_params;
-                               }
                        }
                        Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area));
                        /* loop for more e*/
                        break;
 
+
                case TCFG_ENDIAN:
                        if (goi->isconfigure) {
                                e = Jim_GetOpt_Nvp(goi, nvp_target_endian, &n);
@@ -3892,9 +4792,8 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                                }
                                target->endianness = n->value;
                        } else {
-                               if (goi->argc != 0) {
+                               if (goi->argc != 0)
                                        goto no_params;
-                               }
                        }
                        n = Jim_Nvp_value2name_simple(nvp_target_endian, target->endianness);
                        if (n->name == NULL) {
@@ -3905,39 +4804,15 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                        /* loop for more */
                        break;
 
-               case TCFG_VARIANT:
-                       if (goi->isconfigure) {
-                               if (goi->argc < 1) {
-                                       Jim_SetResultFormatted(goi->interp,
-                                                                                  "%s ?STRING?",
-                                                                                  n->name);
-                                       return JIM_ERR;
-                               }
-                               if (target->variant) {
-                                       free((void *)(target->variant));
-                               }
-                               e = Jim_GetOpt_String(goi, &cp, NULL);
-                               target->variant = strdup(cp);
-                       } else {
-                               if (goi->argc != 0) {
-                                       goto no_params;
-                               }
-                       }
-                       Jim_SetResultString(goi->interp, target->variant,-1);
-                       /* loop for more */
-                       break;
-
                case TCFG_COREID:
                        if (goi->isconfigure) {
                                e = Jim_GetOpt_Wide(goi, &w);
-                               if (e != JIM_OK) {
+                               if (e != JIM_OK)
                                        return e;
-                               }
-                               target->coreid = (int)w;
+                               target->coreid = (int32_t)w;
                        } else {
-                               if (goi->argc != 0) {
+                               if (goi->argc != 0)
                                        goto no_params;
-                               }
                        }
                        Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size));
                        /* loop for more */
@@ -3947,25 +4822,73 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                        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) {
+                               if (e != JIM_OK)
                                        return e;
-                               }
                                tap = jtag_tap_by_jim_obj(goi->interp, o_t);
-                               if (tap == NULL) {
+                               if (tap == NULL)
                                        return JIM_ERR;
-                               }
-                               /* make this exactly 1 or 0 */
                                target->tap = tap;
+                               target->tap_configured = true;
                        } else {
-                               if (goi->argc != 0) {
+                               if (goi->argc != 0)
                                        goto no_params;
-                               }
                        }
                        Jim_SetResultString(goi->interp, target->tap->dotted_name, -1);
                        /* loop for more e*/
                        break;
+               case TCFG_DBGBASE:
+                       if (goi->isconfigure) {
+                               e = Jim_GetOpt_Wide(goi, &w);
+                               if (e != JIM_OK)
+                                       return e;
+                               target->dbgbase = (uint32_t)w;
+                               target->dbgbase_set = true;
+                       } else {
+                               if (goi->argc != 0)
+                                       goto no_params;
+                       }
+                       Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
+                       /* loop for more */
+                       break;
+               case TCFG_RTOS:
+                       /* RTOS */
+                       {
+                               int result = rtos_create(goi, target);
+                               if (result != JIM_OK)
+                                       return result;
+                       }
+                       /* 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) */
 
@@ -3974,20 +4897,15 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
        return JIM_OK;
 }
 
-static int
-jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
 {
        Jim_GetOptInfo goi;
 
        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);
@@ -4001,19 +4919,17 @@ static int jim_target_mw(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        Jim_GetOptInfo goi;
        Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
 
-       if (goi.argc < 2 || goi.argc > 4)
-       {
+       if (goi.argc < 2 || goi.argc > 4) {
                Jim_SetResultFormatted(goi.interp,
                                "usage: %s [phys] <address> <data> [<count>]", cmd_name);
                return JIM_ERR;
        }
 
        target_write_fn fn;
-       fn = target_write_memory_fast;
+       fn = target_write_memory;
 
        int e;
-       if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0)
-       {
+       if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0) {
                /* consume it */
                struct Jim_Obj *obj;
                e = Jim_GetOpt_Obj(&goi, &obj);
@@ -4034,8 +4950,7 @@ static int jim_target_mw(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
                return e;
 
        jim_wide c = 1;
-       if (goi.argc == 1)
-       {
+       if (goi.argc == 1) {
                e = Jim_GetOpt_Wide(&goi, &c);
                if (e != JIM_OK)
                        return e;
@@ -4043,21 +4958,17 @@ static int jim_target_mw(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
        /* all args must be consumed */
        if (goi.argc != 0)
-       {
                return JIM_ERR;
-       }
 
        struct target *target = Jim_CmdPrivData(goi.interp);
        unsigned data_size;
-       if (strcasecmp(cmd_name, "mww") == 0) {
+       if (strcasecmp(cmd_name, "mww") == 0)
                data_size = 4;
-       }
-       else if (strcasecmp(cmd_name, "mwh") == 0) {
+       else if (strcasecmp(cmd_name, "mwh") == 0)
                data_size = 2;
-       }
-       else if (strcasecmp(cmd_name, "mwb") == 0) {
+       else if (strcasecmp(cmd_name, "mwb") == 0)
                data_size = 1;
-       else {
+       else {
                LOG_ERROR("command '%s' unknown: ", cmd_name);
                return JIM_ERR;
        }
@@ -4065,6 +4976,34 @@ static int jim_target_mw(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        return (target_fill_mem(target, a, fn, data_size, b, c) == ERROR_OK) ? JIM_OK : JIM_ERR;
 }
 
+/**
+*  @brief Reads an array of words/halfwords/bytes from target memory starting at specified address.
+*
+*  Usage: mdw [phys] <address> [<count>] - for 32 bit reads
+*         mdh [phys] <address> [<count>] - for 16 bit reads
+*         mdb [phys] <address> [<count>] - for  8 bit reads
+*
+*  Count defaults to 1.
+*
+*  Calls target_read_memory or target_read_phys_memory depending on
+*  the presence of the "phys" argument
+*  Reads the target memory in blocks of max. 32 bytes, and returns an array of ints formatted
+*  to int representation in base16.
+*  Also outputs read data in a human readable form using command_print
+*
+*  @param phys if present target_read_phys_memory will be used instead of target_read_memory
+*  @param address address where to start the read. May be specified in decimal or hex using the standard "0x" prefix
+*  @param count optional count parameter to read an array of values. If not specified, defaults to 1.
+*  @returns:  JIM_ERR on error or JIM_OK on success and sets the result string to an array of ascii formatted numbers
+*  on success, with [<count>] number of elements.
+*
+*  In case of little endian target:
+*      Example1: "mdw 0x00000000"  returns "10123456"
+*      Exmaple2: "mdh 0x00000000 1" returns "3456"
+*      Example3: "mdb 0x00000000" returns "56"
+*      Example4: "mdh 0x00000000 2" returns "3456 1012"
+*      Example5: "mdb 0x00000000 3" returns "56 34 12"
+**/
 static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
        const char *cmd_name = Jim_GetString(argv[0], NULL);
@@ -4072,112 +5011,101 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        Jim_GetOptInfo goi;
        Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
 
-       if ((goi.argc < 1) || (goi.argc > 3))
-       {
+       if ((goi.argc < 1) || (goi.argc > 3)) {
                Jim_SetResultFormatted(goi.interp,
                                "usage: %s [phys] <address> [<count>]", cmd_name);
                return JIM_ERR;
        }
 
        int (*fn)(struct target *target,
-                       uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
-       fn=target_read_memory;
+                       target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer);
+       fn = target_read_memory;
 
        int e;
-       if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0)
-       {
+       if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0) {
                /* consume it */
                struct Jim_Obj *obj;
                e = Jim_GetOpt_Obj(&goi, &obj);
                if (e != JIM_OK)
                        return e;
 
-               fn=target_read_phys_memory;
+               fn = target_read_phys_memory;
        }
 
-       jim_wide a;
-       e = Jim_GetOpt_Wide(&goi, &a);
-       if (e != JIM_OK) {
+       /* Read address parameter */
+       jim_wide addr;
+       e = Jim_GetOpt_Wide(&goi, &addr);
+       if (e != JIM_OK)
                return JIM_ERR;
-       }
-       jim_wide c;
+
+       /* If next parameter exists, read it out as the count parameter, if not, set it to 1 (default) */
+       jim_wide count;
        if (goi.argc == 1) {
-               e = Jim_GetOpt_Wide(&goi, &c);
-               if (e != JIM_OK) {
+               e = Jim_GetOpt_Wide(&goi, &count);
+               if (e != JIM_OK)
                        return JIM_ERR;
-               }
-       } else {
-               c = 1;
-       }
+       } else
+               count = 1;
 
        /* all args must be consumed */
        if (goi.argc != 0)
-       {
                return JIM_ERR;
-       }
 
-       jim_wide b = 1; /* shut up gcc */
+       jim_wide dwidth = 1; /* shut up gcc */
        if (strcasecmp(cmd_name, "mdw") == 0)
-               b = 4;
+               dwidth = 4;
        else if (strcasecmp(cmd_name, "mdh") == 0)
-               b = 2;
+               dwidth = 2;
        else if (strcasecmp(cmd_name, "mdb") == 0)
-               b = 1;
+               dwidth = 1;
        else {
                LOG_ERROR("command '%s' unknown: ", cmd_name);
                return JIM_ERR;
        }
 
        /* convert count to "bytes" */
-       c = c * b;
+       int bytes = count * dwidth;
 
        struct target *target = Jim_CmdPrivData(goi.interp);
        uint8_t  target_buf[32];
        jim_wide x, y, z;
-       while (c > 0) {
-               y = c;
-               if (y > 16) {
-                       y = 16;
-               }
-               e = fn(target, a, b, y / b, target_buf);
+       while (bytes > 0) {
+               y = (bytes < 16) ? bytes : 16; /* y = min(bytes, 16); */
+
+               /* Try to read out next block */
+               e = fn(target, addr, dwidth, y / dwidth, target_buf);
+
                if (e != ERROR_OK) {
-                       char tmp[10];
-                       snprintf(tmp, sizeof(tmp), "%08lx", (long)a);
-                       Jim_SetResultFormatted(interp, "error reading target @ 0x%s", tmp);
+                       Jim_SetResultFormatted(interp, "error reading target @ 0x%08lx", (long)addr);
                        return JIM_ERR;
                }
 
-               command_print(NULL, "0x%08x ", (int)(a));
-               switch (b) {
+               command_print_sameline(NULL, "0x%08x ", (int)(addr));
+               switch (dwidth) {
                case 4:
-                       for (x = 0; x < 16 && x < y; x += 4)
-                       {
-                               z = target_buffer_get_u32(target, &(target_buf[ x ]));
-                               command_print(NULL, "%08x ", (int)(z));
-                       }
-                       for (; (x < 16) ; x += 4) {
-                               command_print(NULL, "         ");
+                       for (x = 0; x < 16 && x < y; x += 4) {
+                               z = target_buffer_get_u32(target, &(target_buf[x]));
+                               command_print_sameline(NULL, "%08x ", (int)(z));
                        }
+                       for (; (x < 16) ; x += 4)
+                               command_print_sameline(NULL, "         ");
                        break;
                case 2:
-                       for (x = 0; x < 16 && x < y; x += 2)
-                       {
-                               z = target_buffer_get_u16(target, &(target_buf[ x ]));
-                               command_print(NULL, "%04x ", (int)(z));
-                       }
-                       for (; (x < 16) ; x += 2) {
-                               command_print(NULL, "     ");
+                       for (x = 0; x < 16 && x < y; x += 2) {
+                               z = target_buffer_get_u16(target, &(target_buf[x]));
+                               command_print_sameline(NULL, "%04x ", (int)(z));
                        }
+                       for (; (x < 16) ; x += 2)
+                               command_print_sameline(NULL, "     ");
                        break;
                case 1:
                default:
                        for (x = 0 ; (x < 16) && (x < y) ; x += 1) {
-                               z = target_buffer_get_u8(target, &(target_buf[ x ]));
-                               command_print(NULL, "%02x ", (int)(z));
-                       }
-                       for (; (x < 16) ; x += 1) {
-                               command_print(NULL, "   ");
+                               z = target_buffer_get_u8(target, &(target_buf[x]));
+                               command_print_sameline(NULL, "%02x ", (int)(z));
                        }
+                       for (; (x < 16) ; x += 1)
+                               command_print_sameline(NULL, "   ");
                        break;
                }
                /* ascii-ify the bytes */
@@ -4198,10 +5126,10 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
                /* terminate */
                target_buf[16] = 0;
                /* print - with a newline */
-               command_print(NULL, "%s\n", target_buf);
+               command_print_sameline(NULL, "%s\n", target_buf);
                /* NEXT... */
-               c -= 16;
-               a += 16;
+               bytes -= 16;
+               addr += 16;
        }
        return JIM_OK;
 }
@@ -4228,27 +5156,61 @@ 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)
-       {
+       if (argc != 1) {
                Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
                return JIM_ERR;
        }
@@ -4262,8 +5224,7 @@ static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *arg
 
 static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-       if (argc != 1)
-       {
+       if (argc != 1) {
                Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
                return JIM_ERR;
        }
@@ -4272,15 +5233,12 @@ static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
                return jim_target_tap_disabled(interp);
 
        int e;
-       if (!(target_was_examined(target))) {
+       if (!(target_was_examined(target)))
                e = ERROR_TARGET_NOT_EXAMINED;
-       } else {
+       else
                e = target->type->poll(target);
-       }
        if (e != ERROR_OK)
-       {
                return JIM_ERR;
-       }
        return JIM_OK;
 }
 
@@ -4289,8 +5247,7 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        Jim_GetOptInfo goi;
        Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
 
-       if (goi.argc != 2)
-       {
+       if (goi.argc != 2) {
                Jim_WrongNumArgs(interp, 0, argv,
                                "([tT]|[fF]|assert|deassert) BOOL");
                return JIM_ERR;
@@ -4298,8 +5255,7 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
        Jim_Nvp *n;
        int e = Jim_GetOpt_Nvp(&goi, nvp_assert, &n);
-       if (e != JIM_OK)
-       {
+       if (e != JIM_OK) {
                Jim_GetOpt_NvpUnknown(&goi, nvp_assert, 1);
                return e;
        }
@@ -4312,29 +5268,27 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        struct target *target = Jim_CmdPrivData(goi.interp);
        if (!target->tap->enabled)
                return jim_target_tap_disabled(interp);
-       if (!(target_was_examined(target)))
-       {
-               LOG_ERROR("Target not examined yet");
-               return ERROR_TARGET_NOT_EXAMINED;
-       }
-       if (!target->type->assert_reset || !target->type->deassert_reset)
-       {
+
+       if (!target->type->assert_reset || !target->type->deassert_reset) {
                Jim_SetResultFormatted(interp,
                                "No target-specific reset for %s",
                                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. */
        target_free_all_working_areas_restore(target, 0);
 
        /* do the assert */
-       if (n->value == NVP_ASSERT) {
+       if (n->value == NVP_ASSERT)
                e = target->type->assert_reset(target);
-       } else {
+       else
                e = target->type->deassert_reset(target);
-       }
        return (e == ERROR_OK) ? JIM_OK : JIM_ERR;
 }
 
@@ -4357,8 +5311,7 @@ static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *a
        Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
 
        /* params:  <name>  statename timeoutmsecs */
-       if (goi.argc != 2)
-       {
+       if (goi.argc != 2) {
                const char *cmd_name = Jim_GetString(argv[0], NULL);
                Jim_SetResultFormatted(goi.interp,
                                "%s <state_name> <timeout_in_msec>", cmd_name);
@@ -4368,21 +5321,19 @@ static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *a
        Jim_Nvp *n;
        int e = Jim_GetOpt_Nvp(&goi, nvp_target_state, &n);
        if (e != JIM_OK) {
-               Jim_GetOpt_NvpUnknown(&goi, nvp_target_state,1);
+               Jim_GetOpt_NvpUnknown(&goi, nvp_target_state, 1);
                return e;
        }
        jim_wide a;
        e = Jim_GetOpt_Wide(&goi, &a);
-       if (e != JIM_OK) {
+       if (e != JIM_OK)
                return e;
-       }
        struct target *target = Jim_CmdPrivData(interp);
        if (!target->tap->enabled)
                return jim_target_tap_disabled(interp);
 
        e = target_wait_state(target, n->value, a);
-       if (e != ERROR_OK)
-       {
+       if (e != ERROR_OK) {
                Jim_Obj *eObj = Jim_NewIntObj(interp, e);
                Jim_SetResultFormatted(goi.interp,
                                "target: %s wait %s fails (%#s) %s",
@@ -4399,7 +5350,7 @@ static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *a
 static int jim_target_event_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
        struct command_context *cmd_ctx = current_command_context(interp);
-       assert (cmd_ctx != NULL);
+       assert(cmd_ctx != NULL);
 
        struct target *target = Jim_CmdPrivData(interp);
        struct target_event_action *teap = target->event_action;
@@ -4409,8 +5360,7 @@ static int jim_target_event_list(Jim_Interp *interp, int argc, Jim_Obj *const *a
        command_print(cmd_ctx, "%-25s | Body", "Event");
        command_print(cmd_ctx, "------------------------- | "
                        "----------------------------------------");
-       while (teap)
-       {
+       while (teap) {
                Jim_Nvp *opt = Jim_Nvp_value2name_simple(nvp_target_event, teap->event);
                command_print(cmd_ctx, "%-25s | %s",
                                opt->name, Jim_GetString(teap->body, NULL));
@@ -4421,8 +5371,7 @@ static int jim_target_event_list(Jim_Interp *interp, int argc, Jim_Obj *const *a
 }
 static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-       if (argc != 1)
-       {
+       if (argc != 1) {
                Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
                return JIM_ERR;
        }
@@ -4434,16 +5383,14 @@ static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const
 {
        Jim_GetOptInfo goi;
        Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
-       if (goi.argc != 1)
-       {
+       if (goi.argc != 1) {
                const char *cmd_name = Jim_GetString(argv[0], NULL);
                Jim_SetResultFormatted(goi.interp, "%s <eventname>", cmd_name);
                return JIM_ERR;
        }
        Jim_Nvp *n;
        int e = Jim_GetOpt_Nvp(&goi, nvp_target_event, &n);
-       if (e != JIM_OK)
-       {
+       if (e != JIM_OK) {
                Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1);
                return e;
        }
@@ -4542,6 +5489,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",
@@ -4588,14 +5548,13 @@ static int target_create(Jim_GetOptInfo *goi)
        Jim_Obj *new_cmd;
        Jim_Cmd *cmd;
        const char *cp;
-       char *cp2;
        int e;
        int x;
        struct target *target;
        struct command_context *cmd_ctx;
 
        cmd_ctx = current_command_context(goi->interp);
-       assert (cmd_ctx != NULL);
+       assert(cmd_ctx != NULL);
 
        if (goi->argc < 3) {
                Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options...");
@@ -4613,14 +5572,33 @@ static int target_create(Jim_GetOptInfo *goi)
        }
 
        /* TYPE */
-       e = Jim_GetOpt_String(goi, &cp2, NULL);
-       cp = cp2;
+       e = Jim_GetOpt_String(goi, &cp, NULL);
+       if (e != JIM_OK)
+               return e;
+       struct transport *tr = get_current_transport();
+       if (tr->override_target) {
+               e = tr->override_target(&cp);
+               if (e != ERROR_OK) {
+                       LOG_ERROR("The selected transport doesn't support this target");
+                       return JIM_ERR;
+               }
+               LOG_INFO("The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD");
+       }
        /* now does target type exist */
        for (x = 0 ; target_types[x] ; x++) {
                if (0 == strcmp(cp, target_types[x]->name)) {
                        /* found */
                        break;
                }
+
+               /* check for deprecated name */
+               if (target_types[x]->deprecated_name) {
+                       if (0 == strcmp(cp, target_types[x]->deprecated_name)) {
+                               /* found */
+                               LOG_WARNING("target name is deprecated use: \'%s\'", target_types[x]->name);
+                               break;
+                       }
+               }
        }
        if (target_types[x] == NULL) {
                Jim_SetResultFormatted(goi->interp, "Unknown target type %s, try one of ", cp);
@@ -4634,19 +5612,20 @@ static int target_create(Jim_GetOptInfo *goi)
                                Jim_AppendStrings(goi->interp,
                                                                   Jim_GetResult(goi->interp),
                                                                   " or ",
-                                                                  target_types[x]->name,NULL);
+                                                                  target_types[x]->name, NULL);
                        }
                }
                return JIM_ERR;
        }
 
        /* Create it */
-       target = calloc(1,sizeof(struct target));
+       target = calloc(1, sizeof(struct target));
        /* set target number */
        target->target_number = new_target_number();
+       cmd_ctx->current_target = target;
 
        /* allocate memory for each unique target type */
-       target->type = (struct target_type*)calloc(1,sizeof(struct target_type));
+       target->type = calloc(1, sizeof(struct target_type));
 
        memcpy(target->type, target_types[x], sizeof(struct target_type));
 
@@ -4669,36 +5648,46 @@ 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;
 
        target->endianness = TARGET_ENDIAN_UNKNOWN;
 
+       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;
@@ -4709,35 +5698,39 @@ static int target_create(Jim_GetOptInfo *goi)
                target->endianness = TARGET_LITTLE_ENDIAN;
        }
 
-       /* incase variant is not set */
-       if (!target->variant)
-               target->variant = strdup("");
-
        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 */
        {
                struct target **tpp;
                tpp = &(all_targets);
-               while (*tpp) {
+               while (*tpp)
                        tpp = &((*tpp)->next);
-               }
                *tpp = target;
        }
 
        /* now - create the new target name command */
-       const const struct command_registration target_subcommands[] = {
+       const struct command_registration target_subcommands[] = {
                {
                        .chain = target_instance_command_handlers,
                },
@@ -4746,11 +5739,12 @@ static int target_create(Jim_GetOptInfo *goi)
                },
                COMMAND_REGISTRATION_DONE
        };
-       const const struct command_registration target_commands[] = {
+       const struct command_registration target_commands[] = {
                {
                        .name = cp,
                        .mode = COMMAND_ANY,
                        .help = "target command group",
+                       .usage = "",
                        .chain = target_subcommands,
                },
                COMMAND_REGISTRATION_DONE
@@ -4768,28 +5762,25 @@ static int target_create(Jim_GetOptInfo *goi)
 
 static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-       if (argc != 1)
-       {
+       if (argc != 1) {
                Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
                return JIM_ERR;
        }
        struct command_context *cmd_ctx = current_command_context(interp);
-       assert (cmd_ctx != NULL);
+       assert(cmd_ctx != NULL);
 
-       Jim_SetResultString(interp, get_current_target(cmd_ctx)->cmd_name, -1);
+       Jim_SetResultString(interp, target_name(get_current_target(cmd_ctx)), -1);
        return JIM_OK;
 }
 
 static int jim_target_types(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-       if (argc != 1)
-       {
+       if (argc != 1) {
                Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
                return JIM_ERR;
        }
        Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
-       for (unsigned x = 0; NULL != target_types[x]; x++)
-       {
+       for (unsigned x = 0; NULL != target_types[x]; x++) {
                Jim_ListAppendElement(interp, Jim_GetResult(interp),
                        Jim_NewStringObj(interp, target_types[x]->name, -1));
        }
@@ -4798,15 +5789,13 @@ static int jim_target_types(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
 static int jim_target_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-       if (argc != 1)
-       {
+       if (argc != 1) {
                Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
                return JIM_ERR;
        }
        Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
        struct target *target = all_targets;
-       while (target)
-       {
+       while (target) {
                Jim_ListAppendElement(interp, Jim_GetResult(interp),
                        Jim_NewStringObj(interp, target_name(target), -1));
                target = target->next;
@@ -4814,70 +5803,68 @@ static int jim_target_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        return JIM_OK;
 }
 
-static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-       Jim_GetOptInfo goi;
-       Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
-       if (goi.argc < 3)
-       {
-               Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
-                       "<name> <target_type> [<target_options> ...]");
-               return JIM_ERR;
-       }
-       return target_create(&goi);
-}
+       int i;
+       const char *targetname;
+       int retval, len;
+       struct target *target = (struct target *) NULL;
+       struct target_list *head, *curr, *new;
+       curr = (struct target_list *) NULL;
+       head = (struct target_list *) NULL;
+
+       retval = 0;
+       LOG_DEBUG("%d", argc);
+       /* argv[1] = target to associate in smp
+        * argv[2] = target to assoicate in smp
+        * argv[3] ...
+        */
 
-static int jim_target_number(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
-       Jim_GetOptInfo goi;
-       Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
+       for (i = 1; i < argc; i++) {
+
+               targetname = Jim_GetString(argv[i], &len);
+               target = get_target(targetname);
+               LOG_DEBUG("%s ", targetname);
+               if (target) {
+                       new = malloc(sizeof(struct target_list));
+                       new->target = target;
+                       new->next = (struct target_list *)NULL;
+                       if (head == (struct target_list *)NULL) {
+                               head = new;
+                               curr = head;
+                       } else {
+                               curr->next = new;
+                               curr = new;
+                       }
+               }
+       }
+       /*  now parse the list of cpu and put the target in smp mode*/
+       curr = head;
 
-       /* It's OK to remove this mechanism sometime after August 2010 or so */
-       LOG_WARNING("don't use numbers as target identifiers; use names");
-       if (goi.argc != 1)
-       {
-               Jim_SetResultFormatted(goi.interp, "usage: target number <number>");
-               return JIM_ERR;
+       while (curr != (struct target_list *)NULL) {
+               target = curr->target;
+               target->smp = 1;
+               target->head = head;
+               curr = curr->next;
        }
-       jim_wide w;
-       int e = Jim_GetOpt_Wide(&goi, &w);
-       if (e != JIM_OK)
-               return JIM_ERR;
 
-       struct target *target;
-       for (target = all_targets; NULL != target; target = target->next)
-       {
-               if (target->target_number != w)
-                       continue;
+       if (target && target->rtos)
+               retval = rtos_smp_init(head->target);
 
-               Jim_SetResultString(goi.interp, target_name(target), -1);
-               return JIM_OK;
-       }
-       {
-               Jim_Obj *wObj = Jim_NewIntObj(goi.interp, w);
-               Jim_SetResultFormatted(goi.interp,
-                       "Target: number %#s does not exist", wObj);
-               Jim_FreeNewObj(interp, wObj);
-       }
-       return JIM_ERR;
+       return retval;
 }
 
-static int jim_target_count(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+
+static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-       if (argc != 1)
-       {
-               Jim_WrongNumArgs(interp, 1, argv, "<no parameters>");
+       Jim_GetOptInfo goi;
+       Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
+       if (goi.argc < 3) {
+               Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
+                       "<name> <target_type> [<target_options> ...]");
                return JIM_ERR;
        }
-       unsigned count = 0;
-       struct target *target = all_targets;
-       while (NULL != target)
-       {
-               target = target->next;
-               count++;
-       }
-       Jim_SetResult(interp, Jim_NewIntObj(interp, count));
-       return JIM_OK;
+       return target_create(&goi);
 }
 
 static const struct command_registration target_subcommand_handlers[] = {
@@ -4889,8 +5876,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",
@@ -4915,26 +5901,18 @@ static const struct command_registration target_subcommand_handlers[] = {
                .help = "Returns the names of all targets as a list of strings",
        },
        {
-               .name = "number",
+               .name = "smp",
                .mode = COMMAND_ANY,
-               .jim_handler = jim_target_number,
-               .usage = "number",
-               .help = "Returns the name of the numbered target "
-                       "(DEPRECATED)",
-       },
-       {
-               .name = "count",
-               .mode = COMMAND_ANY,
-               .jim_handler = jim_target_count,
-               .help = "Returns the number of targets as an integer "
-                       "(DEPRECATED)",
+               .jim_handler = jim_target_smp,
+               .usage = "targetname1 targetname2 ...",
+               .help = "gather several target in a smp list"
        },
+
        COMMAND_REGISTRATION_DONE
 };
 
-struct FastLoad
-{
-       uint32_t address;
+struct FastLoad {
+       target_addr_t address;
        uint8_t *data;
        int length;
 
@@ -4945,11 +5923,9 @@ static struct FastLoad *fastload;
 
 static void free_fastload(void)
 {
-       if (fastload != NULL)
-       {
+       if (fastload != NULL) {
                int i;
-               for (i = 0; i < fastload_num; i++)
-               {
+               for (i = 0; i < fastload_num; i++) {
                        if (fastload[i].data)
                                free(fastload[i].data);
                }
@@ -4958,16 +5934,13 @@ static void free_fastload(void)
        }
 }
 
-
-
-
 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;
@@ -4982,34 +5955,29 @@ COMMAND_HANDLER(handle_fast_load_image_command)
 
        retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL);
        if (retval != ERROR_OK)
-       {
                return retval;
-       }
 
        image_size = 0x0;
        retval = ERROR_OK;
        fastload_num = image.num_sections;
-       fastload = (struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);
-       if (fastload == NULL)
-       {
+       fastload = malloc(sizeof(struct FastLoad)*image.num_sections);
+       if (fastload == NULL) {
                command_print(CMD_CTX, "out of memory");
                image_close(&image);
                return ERROR_FAIL;
        }
        memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections);
-       for (i = 0; i < image.num_sections; i++)
-       {
+       for (i = 0; i < image.num_sections; i++) {
                buffer = malloc(image.sections[i].size);
-               if (buffer == NULL)
-               {
+               if (buffer == NULL) {
                        command_print(CMD_CTX, "error allocating buffer for section (%d bytes)",
                                                  (int)(image.sections[i].size));
                        retval = ERROR_FAIL;
                        break;
                }
 
-               if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
-               {
+               retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt);
+               if (retval != ERROR_OK) {
                        free(buffer);
                        break;
                }
@@ -5017,30 +5985,24 @@ COMMAND_HANDLER(handle_fast_load_image_command)
                uint32_t offset = 0;
                uint32_t length = buf_cnt;
 
-
                /* DANGER!!! beware of unsigned comparision here!!! */
 
-               if ((image.sections[i].base_address + buf_cnt >= min_address)&&
-                               (image.sections[i].base_address < max_address))
-               {
-                       if (image.sections[i].base_address < min_address)
-                       {
+               if ((image.sections[i].base_address + buf_cnt >= min_address) &&
+                               (image.sections[i].base_address < max_address)) {
+                       if (image.sections[i].base_address < min_address) {
                                /* clip addresses below */
                                offset += min_address-image.sections[i].base_address;
                                length -= offset;
                        }
 
                        if (image.sections[i].base_address + buf_cnt > max_address)
-                       {
                                length -= (image.sections[i].base_address + buf_cnt)-max_address;
-                       }
 
                        fastload[i].address = image.sections[i].base_address + offset;
                        fastload[i].data = malloc(length);
-                       if (fastload[i].data == NULL)
-                       {
+                       if (fastload[i].data == NULL) {
                                free(buffer);
-                               command_print(CMD_CTX, "error allocating buffer for section (%d bytes)",
+                               command_print(CMD_CTX, "error allocating buffer for section (%" PRIu32 " bytes)",
                                                          length);
                                retval = ERROR_FAIL;
                                break;
@@ -5057,8 +6019,7 @@ COMMAND_HANDLER(handle_fast_load_image_command)
                free(buffer);
        }
 
-       if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
-       {
+       if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
                command_print(CMD_CTX, "Loaded %" PRIu32 " bytes "
                                "in %fs (%0.3f KiB/s)", image_size,
                                duration_elapsed(&bench), duration_kbps(&bench, image_size));
@@ -5071,9 +6032,7 @@ COMMAND_HANDLER(handle_fast_load_image_command)
        image_close(&image);
 
        if (retval != ERROR_OK)
-       {
                free_fastload();
-       }
 
        return retval;
 }
@@ -5082,31 +6041,26 @@ COMMAND_HANDLER(handle_fast_load_command)
 {
        if (CMD_ARGC > 0)
                return ERROR_COMMAND_SYNTAX_ERROR;
-       if (fastload == NULL)
-       {
+       if (fastload == NULL) {
                LOG_ERROR("No image in memory");
                return ERROR_FAIL;
        }
        int i;
-       int ms = timeval_ms();
+       int64_t ms = timeval_ms();
        int size = 0;
        int retval = ERROR_OK;
-       for (i = 0; i < fastload_num;i++)
-       {
+       for (i = 0; i < fastload_num; i++) {
                struct target *target = get_current_target(CMD_CTX);
                command_print(CMD_CTX, "Write to 0x%08x, length 0x%08x",
                                          (unsigned int)(fastload[i].address),
                                          (unsigned int)(fastload[i].length));
                retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data);
                if (retval != ERROR_OK)
-               {
                        break;
-               }
                size += fastload[i].length;
        }
-       if (retval == ERROR_OK)
-       {
-               int after = timeval_ms();
+       if (retval == ERROR_OK) {
+               int64_t after = timeval_ms();
                command_print(CMD_CTX, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0));
        }
        return retval;
@@ -5150,6 +6104,219 @@ COMMAND_HANDLER(handle_target_reset_nag)
                        "performance");
 }
 
+COMMAND_HANDLER(handle_ps_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       char *display;
+       if (target->state != TARGET_HALTED) {
+               LOG_INFO("target not halted !!");
+               return ERROR_OK;
+       }
+
+       if ((target->rtos) && (target->rtos->type)
+                       && (target->rtos->type->ps_command)) {
+               display = target->rtos->type->ps_command(target);
+               command_print(CMD_CTX, "%s", display);
+               free(display);
+               return ERROR_OK;
+       } else {
+               LOG_INFO("failed");
+               return ERROR_TARGET_FAILURE;
+       }
+}
+
+static void binprint(struct command_context *cmd_ctx, const char *text, const uint8_t *buf, int size)
+{
+       if (text != NULL)
+               command_print_sameline(cmd_ctx, "%s", text);
+       for (int i = 0; i < size; i++)
+               command_print_sameline(cmd_ctx, " %02x", buf[i]);
+       command_print(cmd_ctx, " ");
+}
+
+COMMAND_HANDLER(handle_test_mem_access_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       uint32_t test_size;
+       int retval = ERROR_OK;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_INFO("target not halted !!");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], test_size);
+
+       /* Test reads */
+       size_t num_bytes = test_size + 4;
+
+       struct working_area *wa = NULL;
+       retval = target_alloc_working_area(target, num_bytes, &wa);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Not enough working area");
+               return ERROR_FAIL;
+       }
+
+       uint8_t *test_pattern = malloc(num_bytes);
+
+       for (size_t i = 0; i < num_bytes; i++)
+               test_pattern[i] = rand();
+
+       retval = target_write_memory(target, wa->address, 1, num_bytes, test_pattern);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Test pattern write failed");
+               goto out;
+       }
+
+       for (int host_offset = 0; host_offset <= 1; host_offset++) {
+               for (int size = 1; size <= 4; size *= 2) {
+                       for (int offset = 0; offset < 4; offset++) {
+                               uint32_t count = test_size / size;
+                               size_t host_bufsiz = (count + 2) * size + host_offset;
+                               uint8_t *read_ref = malloc(host_bufsiz);
+                               uint8_t *read_buf = malloc(host_bufsiz);
+
+                               for (size_t i = 0; i < host_bufsiz; i++) {
+                                       read_ref[i] = rand();
+                                       read_buf[i] = read_ref[i];
+                               }
+                               command_print_sameline(CMD_CTX,
+                                               "Test read %" PRIu32 " x %d @ %d to %saligned buffer: ", count,
+                                               size, offset, host_offset ? "un" : "");
+
+                               struct duration bench;
+                               duration_start(&bench);
+
+                               retval = target_read_memory(target, wa->address + offset, size, count,
+                                               read_buf + size + host_offset);
+
+                               duration_measure(&bench);
+
+                               if (retval == ERROR_TARGET_UNALIGNED_ACCESS) {
+                                       command_print(CMD_CTX, "Unsupported alignment");
+                                       goto next;
+                               } else if (retval != ERROR_OK) {
+                                       command_print(CMD_CTX, "Memory read failed");
+                                       goto next;
+                               }
+
+                               /* replay on host */
+                               memcpy(read_ref + size + host_offset, test_pattern + offset, count * size);
+
+                               /* check result */
+                               int result = memcmp(read_ref, read_buf, host_bufsiz);
+                               if (result == 0) {
+                                       command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)",
+                                                       duration_elapsed(&bench),
+                                                       duration_kbps(&bench, count * size));
+                               } else {
+                                       command_print(CMD_CTX, "Compare failed");
+                                       binprint(CMD_CTX, "ref:", read_ref, host_bufsiz);
+                                       binprint(CMD_CTX, "buf:", read_buf, host_bufsiz);
+                               }
+next:
+                               free(read_ref);
+                               free(read_buf);
+                       }
+               }
+       }
+
+out:
+       free(test_pattern);
+
+       if (wa != NULL)
+               target_free_working_area(target, wa);
+
+       /* Test writes */
+       num_bytes = test_size + 4 + 4 + 4;
+
+       retval = target_alloc_working_area(target, num_bytes, &wa);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Not enough working area");
+               return ERROR_FAIL;
+       }
+
+       test_pattern = malloc(num_bytes);
+
+       for (size_t i = 0; i < num_bytes; i++)
+               test_pattern[i] = rand();
+
+       for (int host_offset = 0; host_offset <= 1; host_offset++) {
+               for (int size = 1; size <= 4; size *= 2) {
+                       for (int offset = 0; offset < 4; offset++) {
+                               uint32_t count = test_size / size;
+                               size_t host_bufsiz = count * size + host_offset;
+                               uint8_t *read_ref = malloc(num_bytes);
+                               uint8_t *read_buf = malloc(num_bytes);
+                               uint8_t *write_buf = malloc(host_bufsiz);
+
+                               for (size_t i = 0; i < host_bufsiz; i++)
+                                       write_buf[i] = rand();
+                               command_print_sameline(CMD_CTX,
+                                               "Test write %" PRIu32 " x %d @ %d from %saligned buffer: ", count,
+                                               size, offset, host_offset ? "un" : "");
+
+                               retval = target_write_memory(target, wa->address, 1, num_bytes, test_pattern);
+                               if (retval != ERROR_OK) {
+                                       command_print(CMD_CTX, "Test pattern write failed");
+                                       goto nextw;
+                               }
+
+                               /* replay on host */
+                               memcpy(read_ref, test_pattern, num_bytes);
+                               memcpy(read_ref + size + offset, write_buf + host_offset, count * size);
+
+                               struct duration bench;
+                               duration_start(&bench);
+
+                               retval = target_write_memory(target, wa->address + size + offset, size, count,
+                                               write_buf + host_offset);
+
+                               duration_measure(&bench);
+
+                               if (retval == ERROR_TARGET_UNALIGNED_ACCESS) {
+                                       command_print(CMD_CTX, "Unsupported alignment");
+                                       goto nextw;
+                               } else if (retval != ERROR_OK) {
+                                       command_print(CMD_CTX, "Memory write failed");
+                                       goto nextw;
+                               }
+
+                               /* read back */
+                               retval = target_read_memory(target, wa->address, 1, num_bytes, read_buf);
+                               if (retval != ERROR_OK) {
+                                       command_print(CMD_CTX, "Test pattern write failed");
+                                       goto nextw;
+                               }
+
+                               /* check result */
+                               int result = memcmp(read_ref, read_buf, num_bytes);
+                               if (result == 0) {
+                                       command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)",
+                                                       duration_elapsed(&bench),
+                                                       duration_kbps(&bench, count * size));
+                               } else {
+                                       command_print(CMD_CTX, "Compare failed");
+                                       binprint(CMD_CTX, "ref:", read_ref, num_bytes);
+                                       binprint(CMD_CTX, "buf:", read_buf, num_bytes);
+                               }
+nextw:
+                               free(read_ref);
+                               free(read_buf);
+                       }
+               }
+       }
+
+       free(test_pattern);
+
+       if (wa != NULL)
+               target_free_working_area(target, wa);
+       return retval;
+}
+
 static const struct command_registration target_exec_command_handlers[] = {
        {
                .name = "fast_load_image",
@@ -5166,11 +6333,13 @@ static const struct command_registration target_exec_command_handlers[] = {
                .mode = COMMAND_EXEC,
                .help = "loads active fast load image to current target "
                        "- mainly for profiling purposes",
+               .usage = "",
        },
        {
                .name = "profile",
                .handler = handle_profile_command,
                .mode = COMMAND_EXEC,
+               .usage = "seconds filename [start end]",
                .help = "profiling samples the CPU PC",
        },
        /** @todo don't register virt2phys() unless target supports it */
@@ -5185,9 +6354,9 @@ static const struct command_registration target_exec_command_handlers[] = {
                .name = "reg",
                .handler = handle_reg_command,
                .mode = COMMAND_EXEC,
-               .help = "display or set a register; with no arguments, "
-                       "displays all registers and their values",
-               .usage = "[(register_name|register_number) [value]]",
+               .help = "display (reread from target with \"force\") or set a register; "
+                       "with no arguments, displays all registers and their values",
+               .usage = "[(register_number|register_name) [(value|'force')]]",
        },
        {
                .name = "poll",
@@ -5201,7 +6370,7 @@ static const struct command_registration target_exec_command_handlers[] = {
                .handler = handle_wait_halt_command,
                .mode = COMMAND_EXEC,
                .help = "wait up to the specified number of milliseconds "
-                       "(default 5) for a previously requested halt",
+                       "(default 5000) for a previously requested halt",
                .usage = "[milliseconds]",
        },
        {
@@ -5209,7 +6378,7 @@ static const struct command_registration target_exec_command_handlers[] = {
                .handler = handle_halt_command,
                .mode = COMMAND_EXEC,
                .help = "request target to halt, then wait up to the specified"
-                       "number of milliseconds (default 5) for it to complete",
+                       "number of milliseconds (default 5000) for it to complete",
                .usage = "[milliseconds]",
        },
        {
@@ -5231,6 +6400,7 @@ static const struct command_registration target_exec_command_handlers[] = {
                .name = "soft_reset_halt",
                .handler = handle_soft_reset_halt_command,
                .mode = COMMAND_EXEC,
+               .usage = "",
                .help = "halt the target and do a soft reset",
        },
        {
@@ -5240,6 +6410,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,
@@ -5261,6 +6438,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,
@@ -5287,7 +6471,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 length ['hw']]",
+               .usage = "<address> [<asid>] <length> ['hw'|'hw_ctx']",
        },
        {
                .name = "rbp",
@@ -5323,6 +6507,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,
@@ -5359,15 +6549,32 @@ static const struct command_registration target_exec_command_handlers[] = {
                                "enabled to improve performance. ",
                .usage = "['enable'|'disable']",
        },
+       {
+               .name = "ps",
+               .handler = handle_ps_command,
+               .mode = COMMAND_EXEC,
+               .help = "list all tasks ",
+               .usage = " ",
+       },
+       {
+               .name = "test_mem_access",
+               .handler = handle_test_mem_access_command,
+               .mode = COMMAND_EXEC,
+               .help = "Test the target's memory access functions",
+               .usage = "size",
+       },
+
        COMMAND_REGISTRATION_DONE
 };
 static int target_register_user_commands(struct command_context *cmd_ctx)
 {
        int retval = ERROR_OK;
-       if ((retval = target_request_register_commands(cmd_ctx)) != ERROR_OK)
+       retval = target_request_register_commands(cmd_ctx);
+       if (retval != ERROR_OK)
                return retval;
 
-       if ((retval = trace_register_commands(cmd_ctx)) != ERROR_OK)
+       retval = trace_register_commands(cmd_ctx);
+       if (retval != ERROR_OK)
                return retval;
 
 

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)