target: Use proper data types for timer callback
[openocd.git] / src / target / target.c
index d78f3b1..a3230d2 100644 (file)
@@ -34,9 +34,7 @@
  *   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.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_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, uint32_t address,
+static int target_read_buffer_default(struct target *target, target_addr_t address,
                uint32_t count, uint8_t *buffer);
-static int target_write_buffer_default(struct target *target, uint32_t address,
+static int target_write_buffer_default(struct target *target, target_addr_t address,
                uint32_t count, const uint8_t *buffer);
 static int target_array2mem(Jim_Interp *interp, struct target *target,
                int argc, Jim_Obj * const *argv);
@@ -88,9 +88,11 @@ extern struct target_type feroceon_target;
 extern struct target_type dragonite_target;
 extern struct target_type xscale_target;
 extern struct target_type cortexm_target;
-extern struct target_type cortexa8_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;
@@ -102,6 +104,12 @@ 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,
@@ -116,9 +124,10 @@ static struct target_type *target_types[] = {
        &dragonite_target,
        &xscale_target,
        &cortexm_target,
-       &cortexa8_target,
+       &cortexa_target,
        &cortexr4_target,
        &arm11_target,
+       &ls1_sap_target,
        &mips_m4k_target,
        &avr_target,
        &dsp563xx_target,
@@ -130,12 +139,23 @@ static struct target_type *target_types[] = {
        &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;
 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[] = {
@@ -191,10 +211,6 @@ static const Jim_Nvp nvp_target_event[] = {
        { .value = TARGET_EVENT_RESET_ASSERT_POST,   .name = "reset-assert-post" },
        { .value = TARGET_EVENT_RESET_DEASSERT_PRE,  .name = "reset-deassert-pre" },
        { .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" },
-       { .value = TARGET_EVENT_RESET_HALT_PRE,      .name = "reset-halt-pre" },
-       { .value = TARGET_EVENT_RESET_HALT_POST,     .name = "reset-halt-post" },
-       { .value = TARGET_EVENT_RESET_WAIT_PRE,      .name = "reset-wait-pre" },
-       { .value = TARGET_EVENT_RESET_WAIT_POST,     .name = "reset-wait-post" },
        { .value = TARGET_EVENT_RESET_INIT,          .name = "reset-init" },
        { .value = TARGET_EVENT_RESET_END,           .name = "reset-end" },
 
@@ -213,6 +229,8 @@ 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_TRACE_CONFIG, .name = "trace-config" },
+
        { .name = NULL, .value = -1 }
 };
 
@@ -274,6 +292,32 @@ const char *target_state_name(struct target *t)
                LOG_ERROR("Invalid target state: %d", (int)(t->state));
                cp = "(*BUG*unknown*BUG*)";
        }
+
+       if (!target_was_examined(t) && t->defer_examine)
+               cp = "examine deferred";
+
+       return cp;
+}
+
+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;
 }
 
@@ -294,6 +338,15 @@ static int new_target_number(void)
        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)
 {
@@ -327,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)
 {
@@ -360,6 +422,14 @@ 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)
 {
@@ -376,8 +446,16 @@ void target_buffer_get_u16_array(struct target *target, const uint8_t *buffer, u
                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, uint32_t *srcbuf)
+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++)
@@ -385,7 +463,7 @@ void target_buffer_set_u32_array(struct target *target, uint8_t *buffer, uint32_
 }
 
 /* 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, uint16_t *srcbuf)
+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++)
@@ -424,7 +502,7 @@ 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;
 
@@ -439,7 +517,7 @@ static struct target *get_target_by_num(int num)
 
 struct target *get_current_target(struct command_context *cmd_ctx)
 {
-       struct target *target = get_target_by_num(cmd_ctx->current_target);
+       struct target *target = get_current_target_or_null(cmd_ctx);
 
        if (target == NULL) {
                LOG_ERROR("BUG: current_target out of bounds");
@@ -449,6 +527,13 @@ struct target *get_current_target(struct command_context *cmd_ctx)
        return target;
 }
 
+struct target *get_current_target_or_null(struct command_context *cmd_ctx)
+{
+       return cmd_ctx->current_target_override
+               ? cmd_ctx->current_target_override
+               : cmd_ctx->current_target;
+}
+
 int target_poll(struct target *target)
 {
        int retval;
@@ -467,7 +552,7 @@ int target_poll(struct target *target)
                if (target->state == TARGET_HALTED)
                        target->halt_issued = false;
                else {
-                       long long t = timeval_ms() - target->halt_issued_time;
+                       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.");
@@ -528,7 +613,8 @@ int target_halt(struct target *target)
  * hand the infrastructure for running such helpers might use this
  * procedure but rely on hardware breakpoint to detect termination.)
  */
-int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
+int target_resume(struct target *target, int current, target_addr_t address,
+               int handle_breakpoints, int debug_execution)
 {
        int retval;
 
@@ -564,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.
@@ -586,7 +676,6 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res
        /* 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;
@@ -596,7 +685,7 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res
 }
 
 static int identity_virt2phys(struct target *target,
-               uint32_t virtual, uint32_t *physical)
+               target_addr_t virtual, target_addr_t *physical)
 {
        *physical = virtual;
        return ERROR_OK;
@@ -622,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)
@@ -634,15 +731,7 @@ static int jtag_enable_callback(enum jtag_event event, void *priv)
 
        jtag_unregister_event_callback(jtag_enable_callback, target);
 
-       target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START);
-
-       int retval = target_examine_one(target);
-       if (retval != ERROR_OK)
-               return retval;
-
-       target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END);
-
-       return retval;
+       return target_examine_one(target);
 }
 
 /* Targets that correctly implement init + examine, i.e.
@@ -663,13 +752,12 @@ int target_examine(void)
                        continue;
                }
 
-               target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START);
+               if (target->defer_examine)
+                       continue;
 
                retval = target_examine_one(target);
                if (retval != ERROR_OK)
                        return retval;
-
-               target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END);
        }
        return retval;
 }
@@ -734,8 +822,7 @@ done:
 }
 
 /**
- * Downloads a target-specific native code algorithm to the target,
- * executes and leaves it running.
+ * Executes a target-specific native code algorithm and leaves it running.
  *
  * @param target used to run the algorithm
  * @param arch_info target-specific description of the algorithm.
@@ -808,16 +895,49 @@ done:
 }
 
 /**
- * Executes a target-specific native code algorithm in the target.
- * It differs from target_run_algorithm in that the algorithm is asynchronous.
- * Because of this it requires an compliant algorithm:
- * see contrib/loaders/flash/stm32f1x.S for example.
+ * Streams data to a circular buffer on target intended for consumption by code
+ * running asynchronously on target.
+ *
+ * This is intended for applications where target-specific native code runs
+ * on the target, receives data from the circular buffer, does something with
+ * it (most likely writing it to a flash memory), and advances the circular
+ * buffer pointer.
+ *
+ * This assumes that the helper algorithm has already been loaded to the target,
+ * but has not been started yet. Given memory and register parameters are passed
+ * to the algorithm.
+ *
+ * The buffer is defined by (buffer_start, buffer_size) arguments and has the
+ * following format:
+ *
+ *     [buffer_start + 0, buffer_start + 4):
+ *         Write Pointer address (aka head). Written and updated by this
+ *         routine when new data is written to the circular buffer.
+ *     [buffer_start + 4, buffer_start + 8):
+ *         Read Pointer address (aka tail). Updated by code running on the
+ *         target after it consumes data.
+ *     [buffer_start + 8, buffer_start + buffer_size):
+ *         Circular buffer contents.
+ *
+ * See contrib/loaders/flash/stm32f1x.S for an example.
  *
  * @param target used to run the algorithm
+ * @param buffer address on the host where data to be sent is located
+ * @param count number of blocks to send
+ * @param block_size size in bytes of each block
+ * @param num_mem_params count of memory-based params to pass to algorithm
+ * @param mem_params memory-based params to pass to algorithm
+ * @param num_reg_params count of register-based params to pass to algorithm
+ * @param reg_params memory-based params to pass to algorithm
+ * @param buffer_start address on the target of the circular buffer structure
+ * @param buffer_size size of the circular buffer structure
+ * @param entry_point address on the target to execute to start the algorithm
+ * @param exit_point address at which to set a breakpoint to catch the
+ *     end of the algorithm; can be 0 if target triggers a breakpoint itself
  */
 
 int target_run_flash_async_algorithm(struct target *target,
-               uint8_t *buffer, uint32_t count, int block_size,
+               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,
@@ -826,6 +946,8 @@ int target_run_flash_async_algorithm(struct target *target,
        int retval;
        int timeout = 0;
 
+       const uint8_t *buffer_orig = buffer;
+
        /* 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;
@@ -866,7 +988,8 @@ int target_run_flash_async_algorithm(struct target *target,
                        break;
                }
 
-               LOG_DEBUG("count 0x%" PRIx32 " wp 0x%" PRIx32 " rp 0x%" PRIx32, count, wp, rp);
+               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");
@@ -874,7 +997,7 @@ int target_run_flash_async_algorithm(struct target *target,
                        break;
                }
 
-               if ((rp & (block_size - 1)) || rp < fifo_start_addr || rp >= fifo_end_addr) {
+               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;
                }
@@ -929,6 +1052,9 @@ int target_run_flash_async_algorithm(struct target *target,
                retval = target_write_u32(target, wp_addr, wp);
                if (retval != ERROR_OK)
                        break;
+
+               /* Avoid GDB timeouts */
+               keep_alive();
        }
 
        if (retval != ERROR_OK) {
@@ -947,46 +1073,71 @@ int target_run_flash_async_algorithm(struct target *target,
                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,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+               target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
 {
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                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,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+               target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer)
 {
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                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,
-               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
+               target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                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,
-               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
+               target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                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);
 }
 
@@ -994,7 +1145,7 @@ int target_add_breakpoint(struct target *target,
                struct breakpoint *breakpoint)
 {
        if ((target->state != TARGET_HALTED) && (breakpoint->type != BKPT_HARD)) {
-               LOG_WARNING("target %s is not halted", target_name(target));
+               LOG_WARNING("target %s is not halted (add breakpoint)", target_name(target));
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->add_breakpoint(target, breakpoint);
@@ -1004,7 +1155,7 @@ int target_add_context_breakpoint(struct target *target,
                struct breakpoint *breakpoint)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target_name(target));
+               LOG_WARNING("target %s is not halted (add context breakpoint)", target_name(target));
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->add_context_breakpoint(target, breakpoint);
@@ -1014,7 +1165,7 @@ int target_add_hybrid_breakpoint(struct target *target,
                struct breakpoint *breakpoint)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target_name(target));
+               LOG_WARNING("target %s is not halted (add hybrid breakpoint)", target_name(target));
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->add_hybrid_breakpoint(target, breakpoint);
@@ -1030,7 +1181,7 @@ int target_add_watchpoint(struct target *target,
                struct watchpoint *watchpoint)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target_name(target));
+               LOG_WARNING("target %s is not halted (add watchpoint)", target_name(target));
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->add_watchpoint(target, watchpoint);
@@ -1044,7 +1195,7 @@ int target_hit_watchpoint(struct target *target,
                struct watchpoint **hit_watchpoint)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target->cmd_name);
+               LOG_WARNING("target %s is not halted (hit watchpoint)", target->cmd_name);
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -1058,14 +1209,31 @@ int target_hit_watchpoint(struct target *target,
        return target->type->hit_watchpoint(target, hit_watchpoint);
 }
 
+const char *target_get_gdb_arch(struct target *target)
+{
+       if (target->type->get_gdb_arch == NULL)
+               return NULL;
+       return target->type->get_gdb_arch(target);
+}
+
 int target_get_gdb_reg_list(struct target *target,
                struct reg **reg_list[], int *reg_list_size,
                enum target_register_class reg_class)
 {
        return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, reg_class);
 }
+
+bool target_supports_gdb_connection(struct target *target)
+{
+       /*
+        * based on current code, we can simply exclude all the targets that
+        * don't provide get_gdb_reg_list; this could change with new targets.
+        */
+       return !!target->type->get_gdb_reg_list;
+}
+
 int target_step(struct target *target,
-               int current, uint32_t address, int handle_breakpoints)
+               int current, target_addr_t address, int handle_breakpoints)
 {
        return target->type->step(target, current, address, handle_breakpoints);
 }
@@ -1073,7 +1241,7 @@ int target_step(struct target *target,
 int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target->cmd_name);
+               LOG_WARNING("target %s is not halted (gdb fileio)", target->cmd_name);
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->get_gdb_fileio_info(target, fileio_info);
@@ -1082,7 +1250,7 @@ int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fi
 int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target->cmd_name);
+               LOG_WARNING("target %s is not halted (gdb fileio end)", target->cmd_name);
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c);
@@ -1092,7 +1260,7 @@ int target_profiling(struct target *target, uint32_t *samples,
                        uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
 {
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target %s is not halted", target->cmd_name);
+               LOG_WARNING("target %s is not halted (profiling)", target->cmd_name);
                return ERROR_TARGET_NOT_HALTED;
        }
        return target->type->profiling(target, samples, max_num_samples,
@@ -1108,20 +1276,6 @@ 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, const uint8_t *buffer)
-{
-       LOG_ERROR("Not implemented: %s", __func__);
-       return ERROR_FAIL;
-}
-
 static int handle_target(void *priv);
 
 static int target_init_one(struct command_context *cmd_ctx,
@@ -1148,16 +1302,6 @@ static int target_init_one(struct command_context *cmd_ctx,
         * 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) {
                        LOG_ERROR("type '%s' is missing virt2phys", type->name);
                        type->virt2phys = identity_virt2phys;
@@ -1238,6 +1382,10 @@ COMMAND_HANDLER(handle_target_init_command)
        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;
@@ -1268,10 +1416,54 @@ int target_register_event_callback(int (*callback)(struct target *target,
        return ERROR_OK;
 }
 
-int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)
+int target_register_reset_callback(int (*callback)(struct target *target,
+               enum target_reset_mode reset_mode, void *priv), void *priv)
+{
+       struct target_reset_callback *entry;
+
+       if (callback == NULL)
+               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;
+       }
+
+       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;
-       struct timeval now;
 
        if (callback == NULL)
                return ERROR_COMMAND_SYNTAX_ERROR;
@@ -1284,17 +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;
@@ -1325,26 +1512,58 @@ int target_unregister_event_callback(int (*callback)(struct target *target,
        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_COMMAND_SYNTAX_ERROR;
 
-       while (c) {
-               struct target_timer_callback *next = c->next;
+       list_for_each_entry(entry, &target_reset_callback_list, list) {
+               if (entry->callback == callback && entry->priv == priv) {
+                       list_del(&entry->list);
+                       free(entry);
+                       break;
+               }
+       }
+
+       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;
+               }
+       }
+
+       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)) {
-                       *p = next;
-                       free(c);
+                       c->removed = true;
                        return ERROR_OK;
-               } else
-                       p = &(c->next);
-               c = next;
+               }
        }
 
-       return ERROR_OK;
+       return ERROR_FAIL;
 }
 
 int target_call_event_callbacks(struct target *target, enum target_event event)
@@ -1371,17 +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;
 }
 
@@ -1390,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);
@@ -1398,31 +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;
-               }
+               if (call_it)
+                       target_call_timer_callback(*callback, &now);
 
-               callback = next_callback;
+               callback = &(*callback)->next;
        }
 
+       callback_processing = false;
        return ERROR_OK;
 }
 
@@ -1443,7 +1690,7 @@ static void print_wa_layout(struct target *target)
        struct working_area *c = target->working_areas;
 
        while (c) {
-               LOG_DEBUG("%c%c 0x%08"PRIx32"-0x%08"PRIx32" (%"PRIu32" bytes)",
+               LOG_DEBUG("%c%c " TARGET_ADDR_FMT "-" TARGET_ADDR_FMT " (%" PRIu32 " bytes)",
                        c->backup ? 'b' : ' ', c->free ? ' ' : '*',
                        c->address, c->address + c->size - 1, c->size);
                c = c->next;
@@ -1528,7 +1775,7 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w
                if (!enabled) {
                        if (target->working_area_phys_spec) {
                                LOG_DEBUG("MMU disabled, using physical "
-                                       "address for working memory 0x%08"PRIx32,
+                                       "address for working memory " TARGET_ADDR_FMT,
                                        target->working_area_phys);
                                target->working_area = target->working_area_phys;
                        } else {
@@ -1539,7 +1786,7 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w
                } else {
                        if (target->working_area_virt_spec) {
                                LOG_DEBUG("MMU enabled, using virtual "
-                                       "address for working memory 0x%08"PRIx32,
+                                       "address for working memory " TARGET_ADDR_FMT,
                                        target->working_area_virt);
                                target->working_area = target->working_area_virt;
                        } else {
@@ -1582,7 +1829,8 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w
        /* Split the working area into the requested size */
        target_split_working_area(c, size);
 
-       LOG_DEBUG("allocated new working area of %"PRIu32" bytes at address 0x%08"PRIx32, size, c->address);
+       LOG_DEBUG("allocated new working area of %" PRIu32 " bytes at address " TARGET_ADDR_FMT,
+                         size, c->address);
 
        if (target->backup_working_area) {
                if (c->backup == NULL) {
@@ -1626,7 +1874,7 @@ static int target_restore_working_area(struct target *target, struct working_are
        if (target->backup_working_area && area->backup != NULL) {
                retval = target_write_memory(target, area->address, 4, area->size / 4, area->backup);
                if (retval != ERROR_OK)
-                       LOG_ERROR("failed to restore %"PRIu32" bytes of working area at address 0x%08"PRIx32,
+                       LOG_ERROR("failed to restore %" PRIu32 " bytes of working area at address " TARGET_ADDR_FMT,
                                        area->size, area->address);
        }
 
@@ -1650,7 +1898,7 @@ static int target_free_working_area_restore(struct target *target, struct workin
 
        area->free = true;
 
-       LOG_DEBUG("freed %"PRIu32" bytes of working area at address 0x%08"PRIx32,
+       LOG_DEBUG("freed %" PRIu32 " bytes of working area at address " TARGET_ADDR_FMT,
                        area->size, area->address);
 
        /* mark user pointer invalid */
@@ -1702,6 +1950,14 @@ static void target_free_all_working_areas_restore(struct target *target, int res
 void target_free_all_working_areas(struct target *target)
 {
        target_free_all_working_areas_restore(target, 1);
+
+       /* Now we have none or only one working area marked as free */
+       if (target->working_areas) {
+               /* Free the last one to allow on-the-fly moving and resizing */
+               free(target->working_areas->backup);
+               free(target->working_areas);
+               target->working_areas = NULL;
+       }
 }
 
 /* Find the largest number of bytes that can be allocated */
@@ -1723,16 +1979,83 @@ uint32_t target_get_working_area_avail(struct target *target)
        return max_size;
 }
 
+static void target_destroy(struct target *target)
+{
+       if (target->type->deinit_target)
+               target->type->deinit_target(target);
+
+       if (target->semihosting)
+               free(target->semihosting);
+
+       jtag_unregister_event_callback(jtag_enable_callback, target);
+
+       struct target_event_action *teap = target->event_action;
+       while (teap) {
+               struct target_event_action *next = teap->next;
+               Jim_DecrRefCount(teap->interp, teap->body);
+               free(teap);
+               teap = next;
+       }
+
+       target_free_all_working_areas(target);
+
+       /* release the targets SMP list */
+       if (target->smp) {
+               struct target_list *head = target->head;
+               while (head != NULL) {
+                       struct target_list *pos = head->next;
+                       head->target->smp = 0;
+                       free(head);
+                       head = pos;
+               }
+               target->smp = 0;
+       }
+
+       free(target->gdb_port_override);
+       free(target->type);
+       free(target->trace_info);
+       free(target->fileio_info);
+       free(target->cmd_name);
+       free(target);
+}
+
+void target_quit(void)
+{
+       struct target_event_callback *pe = target_event_callbacks;
+       while (pe) {
+               struct target_event_callback *t = pe->next;
+               free(pe);
+               pe = t;
+       }
+       target_event_callbacks = NULL;
+
+       struct target_timer_callback *pt = target_timer_callbacks;
+       while (pt) {
+               struct target_timer_callback *t = pt->next;
+               free(pt);
+               pt = t;
+       }
+       target_timer_callbacks = NULL;
+
+       for (struct target *target = all_targets; target;) {
+               struct target *tmp;
+
+               tmp = target->next;
+               target_destroy(target);
+               target = tmp;
+       }
+
+       all_targets = NULL;
+}
+
 int target_arch_state(struct target *target)
 {
        int retval;
        if (target == NULL) {
-               LOG_USER("No target has been configured");
+               LOG_WARNING("No target has been configured");
                return ERROR_OK;
        }
 
-       LOG_USER("target state: %s", target_state_name(target));
-
        if (target->state != TARGET_HALTED)
                return ERROR_OK;
 
@@ -1775,7 +2098,7 @@ static int target_profiling_default(struct target *target, uint32_t *samples,
        for (;;) {
                target_poll(target);
                if (target->state == TARGET_HALTED) {
-                       uint32_t t = *((uint32_t *)reg->value);
+                       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);
@@ -1794,8 +2117,7 @@ static int target_profiling_default(struct target *target, uint32_t *samples,
                        break;
 
                gettimeofday(&now, NULL);
-               if ((sample_count >= max_num_samples) ||
-                       ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) {
+               if ((sample_count >= max_num_samples) || timeval_compare(&now, &timeout) >= 0) {
                        LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count);
                        break;
                }
@@ -1809,10 +2131,10 @@ static int target_profiling_default(struct target *target, uint32_t *samples,
  * mode respectively, otherwise data is handled as quickly as
  * possible
  */
-int target_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer)
+int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
 {
-       LOG_DEBUG("writing buffer of %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)) {
                LOG_ERROR("Target not examined yet");
@@ -1823,17 +2145,18 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size,
                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);
+               /* 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;
        }
 
        return target->type->write_buffer(target, address, size, buffer);
 }
 
-static int target_write_buffer_default(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer)
+static int target_write_buffer_default(struct target *target,
+       target_addr_t address, uint32_t count, const uint8_t *buffer)
 {
        uint32_t size;
 
@@ -1870,10 +2193,10 @@ static int target_write_buffer_default(struct target *target, uint32_t address,
  * mode respectively, otherwise data is handled as quickly as
  * possible
  */
-int target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer)
+int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
 {
-       LOG_DEBUG("reading buffer of %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)) {
                LOG_ERROR("Target not examined yet");
@@ -1884,8 +2207,8 @@ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, u
                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 ")",
+               /* 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;
@@ -1894,7 +2217,7 @@ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, u
        return target->type->read_buffer(target, address, size, buffer);
 }
 
-static int target_read_buffer_default(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer)
+static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer)
 {
        uint32_t size;
 
@@ -1927,7 +2250,7 @@ static int target_read_buffer_default(struct target *target, uint32_t address, u
        return ERROR_OK;
 }
 
-int target_checksum_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* crc)
+int target_checksum_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t* crc)
 {
        uint8_t *buffer;
        int retval;
@@ -1942,7 +2265,7 @@ int target_checksum_memory(struct target *target, uint32_t address, uint32_t siz
        if (retval != ERROR_OK) {
                buffer = malloc(size);
                if (buffer == NULL) {
-                       LOG_ERROR("error allocating buffer for section (%d bytes)", (int)size);
+                       LOG_ERROR("error allocating buffer for section (%" PRId32 " bytes)", size);
                        return ERROR_COMMAND_SYNTAX_ERROR;
                }
                retval = target_read_buffer(target, address, size, buffer);
@@ -1967,23 +2290,46 @@ int target_checksum_memory(struct target *target, uint32_t address, uint32_t siz
        return retval;
 }
 
-int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* blank)
+int target_blank_check_memory(struct target *target,
+       struct target_memory_check_block *blocks, int num_blocks,
+       uint8_t erased_value)
 {
-       int retval;
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
                return ERROR_FAIL;
        }
 
-       if (target->type->blank_check_memory == 0)
+       if (target->type->blank_check_memory == NULL)
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
 
-       retval = target->type->blank_check_memory(target, address, size, blank);
+       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)) {
@@ -1995,19 +2341,19 @@ int target_read_u32(struct target *target, uint32_t address, uint32_t *value)
 
        if (retval == ERROR_OK) {
                *value = target_buffer_get_u32(target, value_buf);
-               LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "",
                                  address,
                                  *value);
        } else {
                *value = 0x0;
-               LOG_DEBUG("address: 0x%8.8" PRIx32 " failed",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT " failed",
                                  address);
        }
 
        return retval;
 }
 
-int target_read_u16(struct target *target, uint32_t address, uint16_t *value)
+int target_read_u16(struct target *target, target_addr_t address, uint16_t *value)
 {
        uint8_t value_buf[2];
        if (!target_was_examined(target)) {
@@ -2019,19 +2365,19 @@ int target_read_u16(struct target *target, uint32_t address, uint16_t *value)
 
        if (retval == ERROR_OK) {
                *value = target_buffer_get_u16(target, value_buf);
-               LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%4.4x",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%4.4" PRIx16,
                                  address,
                                  *value);
        } else {
                *value = 0x0;
-               LOG_DEBUG("address: 0x%8.8" PRIx32 " failed",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT " failed",
                                  address);
        }
 
        return retval;
 }
 
-int target_read_u8(struct target *target, uint32_t address, uint8_t *value)
+int target_read_u8(struct target *target, target_addr_t address, uint8_t *value)
 {
        if (!target_was_examined(target)) {
                LOG_ERROR("Target not examined yet");
@@ -2041,19 +2387,40 @@ int target_read_u8(struct target *target, uint32_t address, uint8_t *value)
        int retval = target_read_memory(target, address, 1, 1, value);
 
        if (retval == ERROR_OK) {
-               LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8,
                                  address,
                                  *value);
        } else {
                *value = 0x0;
-               LOG_DEBUG("address: 0x%8.8" PRIx32 " failed",
+               LOG_DEBUG("address: " TARGET_ADDR_FMT " failed",
                                  address);
        }
 
        return retval;
 }
 
-int target_write_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];
@@ -2062,7 +2429,7 @@ int target_write_u32(struct target *target, uint32_t address, uint32_t value)
                return ERROR_FAIL;
        }
 
-       LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "",
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "",
                          address,
                          value);
 
@@ -2074,7 +2441,7 @@ int target_write_u32(struct target *target, uint32_t address, uint32_t value)
        return retval;
 }
 
-int target_write_u16(struct target *target, uint32_t address, uint16_t value)
+int target_write_u16(struct target *target, target_addr_t address, uint16_t value)
 {
        int retval;
        uint8_t value_buf[2];
@@ -2083,7 +2450,7 @@ int target_write_u16(struct target *target, uint32_t address, uint16_t value)
                return ERROR_FAIL;
        }
 
-       LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8x",
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx16,
                          address,
                          value);
 
@@ -2095,7 +2462,7 @@ int target_write_u16(struct target *target, uint32_t address, uint16_t value)
        return retval;
 }
 
-int target_write_u8(struct target *target, uint32_t address, uint8_t value)
+int target_write_u8(struct target *target, target_addr_t address, uint8_t value)
 {
        int retval;
        if (!target_was_examined(target)) {
@@ -2103,7 +2470,7 @@ int target_write_u8(struct target *target, uint32_t address, uint8_t value)
                return ERROR_FAIL;
        }
 
-       LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x",
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8,
                          address, value);
 
        retval = target_write_memory(target, address, 1, 1, &value);
@@ -2113,6 +2480,87 @@ int target_write_u8(struct target *target, uint32_t address, uint8_t value)
        return retval;
 }
 
+int target_write_phys_u64(struct target *target, target_addr_t address, uint64_t value)
+{
+       int retval;
+       uint8_t value_buf[8];
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "",
+                         address,
+                         value);
+
+       target_buffer_set_u64(target, value_buf, value);
+       retval = target_write_phys_memory(target, address, 8, 1, value_buf);
+       if (retval != ERROR_OK)
+               LOG_DEBUG("failed: %i", retval);
+
+       return retval;
+}
+
+int target_write_phys_u32(struct target *target, target_addr_t address, uint32_t value)
+{
+       int retval;
+       uint8_t value_buf[4];
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "",
+                         address,
+                         value);
+
+       target_buffer_set_u32(target, value_buf, value);
+       retval = target_write_phys_memory(target, address, 4, 1, value_buf);
+       if (retval != ERROR_OK)
+               LOG_DEBUG("failed: %i", retval);
+
+       return retval;
+}
+
+int target_write_phys_u16(struct target *target, target_addr_t address, uint16_t value)
+{
+       int retval;
+       uint8_t value_buf[2];
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx16,
+                         address,
+                         value);
+
+       target_buffer_set_u16(target, value_buf, value);
+       retval = target_write_phys_memory(target, address, 2, 1, value_buf);
+       if (retval != ERROR_OK)
+               LOG_DEBUG("failed: %i", retval);
+
+       return retval;
+}
+
+int target_write_phys_u8(struct target *target, target_addr_t address, uint8_t value)
+{
+       int retval;
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8,
+                         address, value);
+
+       retval = target_write_phys_memory(target, address, 1, 1, &value);
+       if (retval != ERROR_OK)
+               LOG_DEBUG("failed: %i", retval);
+
+       return retval;
+}
+
 static int find_target(struct command_context *cmd_ctx, const char *name)
 {
        struct target *target = get_target(name);
@@ -2127,7 +2575,10 @@ static int find_target(struct command_context *cmd_ctx, const char *name)
                return ERROR_FAIL;
        }
 
-       cmd_ctx->current_target = target->target_number;
+       cmd_ctx->current_target = target;
+       if (cmd_ctx->current_target_override)
+               cmd_ctx->current_target_override = target;
+
        return ERROR_OK;
 }
 
@@ -2155,7 +2606,7 @@ COMMAND_HANDLER(handle_targets_command)
                else
                        state = "tap-disabled";
 
-               if (CMD_CTX->current_target == target->target_number)
+               if (CMD_CTX->current_target == target)
                        marker = '*';
 
                /* keep columns lined up to match the headers above */
@@ -2199,9 +2650,9 @@ static int sense_handler(void)
        if (powerRestored)
                runPowerRestore = 1;
 
-       long long current = timeval_ms();
-       static long long lastPower;
-       int waitMore = lastPower + 2000 > current;
+       int64_t current = timeval_ms();
+       static int64_t lastPower;
+       bool waitMore = lastPower + 2000 > current;
        if (powerDropout && !waitMore) {
                runPowerDropout = 1;
                lastPower = current;
@@ -2214,7 +2665,7 @@ static int sense_handler(void)
        int srstDeasserted;
        srstDeasserted = prevSrstAsserted && !srstAsserted;
 
-       static long long lastSrst;
+       static int64_t lastSrst;
        waitMore = lastSrst + 2000 > current;
        if (srstDeasserted && !waitMore) {
                runSrstDeasserted = 1;
@@ -2298,6 +2749,10 @@ static int handle_target(void *priv)
        for (struct target *target = all_targets;
                        is_jtag_poll_safe() && target;
                        target = target->next) {
+
+               if (!target_was_examined(target))
+                       continue;
+
                if (!target->tap->enabled)
                        continue;
 
@@ -2318,19 +2773,27 @@ static int handle_target(void *priv)
                                        target->backoff.times *= 2;
                                        target->backoff.times++;
                                }
-                               LOG_USER("Polling target %s failed, GDB will be halted. Polling again in %dms",
-                                               target_name(target),
-                                               target->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;
                        }
+                       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;
+                               }
+                       }
+
                        /* Since we succeeded, we reset backoff count */
-                       if (target->backoff.times > 0)
-                               LOG_USER("Polling target %s succeeded again", target_name(target));
                        target->backoff.times = 0;
                }
        }
@@ -2362,6 +2825,8 @@ COMMAND_HANDLER(handle_reg_command)
                        for (i = 0, reg = cache->reg_list;
                                        i < cache->num_regs;
                                        i++, reg++, count++) {
+                               if (reg->exist == false)
+                                       continue;
                                /* only print cached values if they are valid */
                                if (reg->valid) {
                                        value = buf_to_str(reg->value,
@@ -2415,14 +2880,15 @@ COMMAND_HANDLER(handle_reg_command)
                /* access a single register by its name */
                reg = register_get_by_name(target->reg_cache, CMD_ARGV[0], 1);
 
-               if (!reg) {
-                       command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]);
-                       return ERROR_OK;
-               }
+               if (!reg)
+                       goto not_found;
        }
 
        assert(reg != NULL); /* give clang a hint that we *know* reg is != NULL here */
 
+       if (!reg->exist)
+               goto not_found;
+
        /* display a register */
        if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0')
                        && (CMD_ARGV[1][0] <= '9')))) {
@@ -2456,6 +2922,10 @@ COMMAND_HANDLER(handle_reg_command)
        }
 
        return ERROR_COMMAND_SYNTAX_ERROR;
+
+not_found:
+       command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]);
+       return ERROR_OK;
 }
 
 COMMAND_HANDLER(handle_poll_command)
@@ -2512,8 +2982,8 @@ 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 (;;) {
                retval = target_poll(target);
@@ -2523,7 +2993,7 @@ int target_wait_state(struct target *target, enum target_state state, int ms)
                        break;
                cur = timeval_ms();
                if (once) {
-                       once = 0;
+                       once = false;
                        then = timeval_ms();
                        LOG_DEBUG("waiting for target %s...",
                                Jim_Nvp_value2name_simple(nvp_target_state, state)->name);
@@ -2547,6 +3017,9 @@ COMMAND_HANDLER(handle_halt_command)
        LOG_DEBUG("-");
 
        struct target *target = get_current_target(CMD_CTX);
+
+       target->verbose_halt_msg = true;
+
        int retval = target_halt(target);
        if (ERROR_OK != retval)
                return retval;
@@ -2604,9 +3077,9 @@ COMMAND_HANDLER(handle_resume_command)
        /* with no CMD_ARGV, resume from current pc, addr = 0,
         * with one arguments, addr = CMD_ARGV[0],
         * handle breakpoints, not debugging */
-       uint32_t addr = 0;
+       target_addr_t addr = 0;
        if (CMD_ARGC == 1) {
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
                current = 0;
        }
 
@@ -2623,10 +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);
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
                current_pc = 0;
        }
 
@@ -2636,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;
@@ -2647,14 +3120,17 @@ static void handle_md_output(struct command_context *cmd_ctx,
 
        const char *value_fmt;
        switch (size) {
+       case 8:
+               value_fmt = "%16.16"PRIx64" ";
+               break;
        case 4:
-               value_fmt = "%8.8x ";
+               value_fmt = "%8.8"PRIx64" ";
                break;
        case 2:
-               value_fmt = "%4.4x ";
+               value_fmt = "%4.4"PRIx64" ";
                break;
        case 1:
-               value_fmt = "%2.2x ";
+               value_fmt = "%2.2"PRIx64" ";
                break;
        default:
                /* "can't happen", caller checked */
@@ -2666,13 +3142,16 @@ static void handle_md_output(struct command_context *cmd_ctx,
                if (i % line_modulo == 0) {
                        output_len += snprintf(output + output_len,
                                        sizeof(output) - output_len,
-                                       "0x%8.8x: ",
-                                       (unsigned)(address + (i*size)));
+                                       TARGET_ADDR_FMT ": ",
+                                       (address + (i * size)));
                }
 
-               uint32_t value = 0;
+               uint64_t value = 0;
                const uint8_t *value_ptr = buffer + i * size;
                switch (size) {
+               case 8:
+                       value = target_buffer_get_u64(target, value_ptr);
+                       break;
                case 4:
                        value = target_buffer_get_u32(target, value_ptr);
                        break;
@@ -2700,6 +3179,9 @@ COMMAND_HANDLER(handle_md_command)
 
        unsigned size = 0;
        switch (CMD_NAME[2]) {
+       case 'd':
+               size = 8;
+               break;
        case 'w':
                size = 4;
                break;
@@ -2715,7 +3197,7 @@ COMMAND_HANDLER(handle_md_command)
 
        bool physical = strcmp(CMD_ARGV[0], "phys") == 0;
        int (*fn)(struct target *target,
-                       uint32_t address, uint32_t size_value, uint32_t count, uint8_t *buffer);
+                       target_addr_t address, uint32_t size_value, uint32_t count, uint8_t *buffer);
        if (physical) {
                CMD_ARGC--;
                CMD_ARGV++;
@@ -2725,14 +3207,18 @@ COMMAND_HANDLER(handle_md_command)
        if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       uint32_t address;
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
+       target_addr_t address;
+       COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
 
        unsigned count = 1;
        if (CMD_ARGC == 2)
                COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count);
 
        uint8_t *buffer = calloc(count, size);
+       if (buffer == NULL) {
+               LOG_ERROR("Failed to allocate md read buffer");
+               return ERROR_FAIL;
+       }
 
        struct target *target = get_current_target(CMD_CTX);
        int retval = fn(target, address, size, count, buffer);
@@ -2745,14 +3231,14 @@ COMMAND_HANDLER(handle_md_command)
 }
 
 typedef int (*target_write_fn)(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
+               target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
 
 static int target_fill_mem(struct target *target,
-               uint32_t address,
+               target_addr_t address,
                target_write_fn fn,
                unsigned data_size,
                /* value */
-               uint32_t b,
+               uint64_t b,
                /* count */
                unsigned c)
 {
@@ -2767,6 +3253,9 @@ static int target_fill_mem(struct target *target,
 
        for (unsigned i = 0; i < chunk_size; i++) {
                switch (data_size) {
+               case 8:
+                       target_buffer_set_u64(target, target_buf + i * data_size, b);
+                       break;
                case 4:
                        target_buffer_set_u32(target, target_buf + i * data_size, b);
                        break;
@@ -2815,11 +3304,11 @@ COMMAND_HANDLER(handle_mw_command)
        if ((CMD_ARGC < 2) || (CMD_ARGC > 3))
                return ERROR_COMMAND_SYNTAX_ERROR;
 
-       uint32_t address;
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
+       target_addr_t address;
+       COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
 
-       uint32_t value;
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
+       target_addr_t value;
+       COMMAND_PARSE_ADDRESS(CMD_ARGV[1], value);
 
        unsigned count = 1;
        if (CMD_ARGC == 3)
@@ -2828,6 +3317,9 @@ COMMAND_HANDLER(handle_mw_command)
        struct target *target = get_current_target(CMD_CTX);
        unsigned wordsize;
        switch (CMD_NAME[2]) {
+               case 'd':
+                       wordsize = 8;
+                       break;
                case 'w':
                        wordsize = 4;
                        break;
@@ -2845,7 +3337,7 @@ COMMAND_HANDLER(handle_mw_command)
 }
 
 static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image,
-               uint32_t *min_address, uint32_t *max_address)
+               target_addr_t *min_address, target_addr_t *max_address)
 {
        if (CMD_ARGC < 1 || CMD_ARGC > 5)
                return ERROR_COMMAND_SYNTAX_ERROR;
@@ -2853,8 +3345,8 @@ static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image,
        /* a base address isn't always necessary,
         * default to 0x0 (i.e. don't relocate) */
        if (CMD_ARGC >= 2) {
-               uint32_t addr;
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
+               target_addr_t addr;
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr);
                image->base_address = addr;
                image->base_address_set = 1;
        } else
@@ -2863,9 +3355,9 @@ static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image,
        image->start_address_set = 0;
 
        if (CMD_ARGC >= 4)
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], *min_address);
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[3], *min_address);
        if (CMD_ARGC == 5) {
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], *max_address);
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[4], *max_address);
                /* use size (given) to find max (required) */
                *max_address += *min_address;
        }
@@ -2881,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;
 
@@ -2897,7 +3389,7 @@ COMMAND_HANDLER(handle_load_image_command)
        duration_start(&bench);
 
        if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK)
-               return ERROR_OK;
+               return ERROR_FAIL;
 
        image_size = 0x0;
        retval = ERROR_OK;
@@ -2907,6 +3399,7 @@ COMMAND_HANDLER(handle_load_image_command)
                        command_print(CMD_CTX,
                                                  "error allocating buffer for section (%d bytes)",
                                                  (int)(image.sections[i].size));
+                       retval = ERROR_FAIL;
                        break;
                }
 
@@ -2940,7 +3433,7 @@ COMMAND_HANDLER(handle_load_image_command)
                                break;
                        }
                        image_size += length;
-                       command_print(CMD_CTX, "%u bytes written at address 0x%8.8" PRIx32 "",
+                       command_print(CMD_CTX, "%u bytes written at address " TARGET_ADDR_FMT "",
                                        (unsigned int)length,
                                        image.sections[i].base_address + offset);
                }
@@ -2962,18 +3455,18 @@ COMMAND_HANDLER(handle_load_image_command)
 
 COMMAND_HANDLER(handle_dump_image_command)
 {
-       struct fileio fileio;
+       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);
@@ -2995,7 +3488,7 @@ COMMAND_HANDLER(handle_dump_image_command)
                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;
 
@@ -3006,23 +3499,29 @@ COMMAND_HANDLER(handle_dump_image_command)
        free(buffer);
 
        if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) {
-               int filesize;
-               retval = fileio_size(&fileio, &filesize);
+               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));
        }
 
-       retvaltemp = fileio_close(&fileio);
+       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;
@@ -3048,8 +3547,8 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
        duration_start(&bench);
 
        if (CMD_ARGC >= 2) {
-               uint32_t addr;
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr);
+               target_addr_t addr;
+               COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr);
                image.base_address = addr;
                image.base_address_set = 1;
        } else {
@@ -3080,7 +3579,7 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
                        break;
                }
 
-               if (verify) {
+               if (verify >= IMAGE_VERIFY) {
                        /* calculate checksum of image */
                        retval = image_calculate_checksum(buffer, buf_cnt, &checksum);
                        if (retval != ERROR_OK) {
@@ -3093,7 +3592,12 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
                                free(buffer);
                                break;
                        }
-
+                       if ((checksum != mem_checksum) && (verify == IMAGE_CHECKSUM_ONLY)) {
+                               LOG_ERROR("checksum mismatch");
+                               free(buffer);
+                               retval = ERROR_FAIL;
+                               goto done;
+                       }
                        if (checksum != mem_checksum) {
                                /* failed crc checksum, fall back to a binary compare */
                                uint8_t *data;
@@ -3101,7 +3605,7 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
                                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;
@@ -3134,7 +3638,7 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify)
                                free(data);
                        }
                } else {
-                       command_print(CMD_CTX, "address 0x%08" PRIx32 " length 0x%08zx",
+                       command_print(CMD_CTX, "address " TARGET_ADDR_FMT " length 0x%08zx",
                                                  image.sections[i].base_address,
                                                  buf_cnt);
                }
@@ -3158,14 +3662,19 @@ done:
        return retval;
 }
 
+COMMAND_HANDLER(handle_verify_image_checksum_command)
+{
+       return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_CHECKSUM_ONLY);
+}
+
 COMMAND_HANDLER(handle_verify_image_command)
 {
-       return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 1);
+       return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_VERIFY);
 }
 
 COMMAND_HANDLER(handle_test_image_command)
 {
-       return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 0);
+       return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_TEST);
 }
 
 static int handle_bp_command_list(struct command_context *cmd_ctx)
@@ -3176,7 +3685,7 @@ static int handle_bp_command_list(struct command_context *cmd_ctx)
                if (breakpoint->type == BKPT_SOFT) {
                        char *buf = buf_to_str(breakpoint->orig_instr,
                                        breakpoint->length, 16);
-                       command_print(cmd_ctx, "IVA breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i, 0x%s",
+                       command_print(cmd_ctx, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, %i, 0x%s",
                                        breakpoint->address,
                                        breakpoint->length,
                                        breakpoint->set, buf);
@@ -3187,13 +3696,13 @@ static int handle_bp_command_list(struct command_context *cmd_ctx)
                                                        breakpoint->asid,
                                                        breakpoint->length, breakpoint->set);
                        else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) {
-                               command_print(cmd_ctx, "Hybrid breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i",
+                               command_print(cmd_ctx, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i",
                                                        breakpoint->address,
                                                        breakpoint->length, breakpoint->set);
                                command_print(cmd_ctx, "\t|--->linked with ContextID: 0x%8.8" PRIx32,
                                                        breakpoint->asid);
                        } else
-                               command_print(cmd_ctx, "Breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i",
+                               command_print(cmd_ctx, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i",
                                                        breakpoint->address,
                                                        breakpoint->length, breakpoint->set);
                }
@@ -3204,41 +3713,43 @@ static int handle_bp_command_list(struct command_context *cmd_ctx)
 }
 
 static int handle_bp_command_set(struct command_context *cmd_ctx,
-               uint32_t addr, uint32_t asid, uint32_t length, int hw)
+               target_addr_t addr, uint32_t asid, uint32_t length, int hw)
 {
        struct target *target = get_current_target(cmd_ctx);
+       int retval;
 
        if (asid == 0) {
-               int retval = breakpoint_add(target, addr, length, hw);
+               retval = breakpoint_add(target, addr, length, hw);
+               /* error is always logged in breakpoint_add(), do not print it again */
                if (ERROR_OK == retval)
-                       command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr);
-               else {
-                       LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used");
-                       return retval;
-               }
+                       command_print(cmd_ctx, "breakpoint set at " TARGET_ADDR_FMT "", addr);
+
        } else if (addr == 0) {
-               int retval = context_breakpoint_add(target, asid, length, hw);
-               if (ERROR_OK == retval)
-                       command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid);
-               else {
-                       LOG_ERROR("Failure setting breakpoint, the same address(CONTEXTID) is already used");
-                       return retval;
+               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 {
-               int retval = hybrid_breakpoint_add(target, addr, asid, length, hw);
+               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);
-               else {
-                       LOG_ERROR("Failure setting breakpoint, the same address is already used");
-                       return retval;
-               }
        }
-       return ERROR_OK;
+       return retval;
 }
 
 COMMAND_HANDLER(handle_bp_command)
 {
-       uint32_t addr;
+       target_addr_t addr;
        uint32_t asid;
        uint32_t length;
        int hw = BKPT_SOFT;
@@ -3249,17 +3760,15 @@ COMMAND_HANDLER(handle_bp_command)
 
                case 2:
                        asid = 0;
-                       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+                       COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
                        COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
                        return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
 
                case 3:
                        if (strcmp(CMD_ARGV[2], "hw") == 0) {
                                hw = BKPT_HARD;
-                               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
-
+                               COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
                                COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length);
-
                                asid = 0;
                                return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
                        } else if (strcmp(CMD_ARGV[2], "hw_ctx") == 0) {
@@ -3269,10 +3778,10 @@ COMMAND_HANDLER(handle_bp_command)
                                addr = 0;
                                return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
                        }
-
+                       /* fallthrough */
                case 4:
                        hw = BKPT_HARD;
-                       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+                       COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr);
                        COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], asid);
                        COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], length);
                        return handle_bp_command_set(CMD_CTX, addr, asid, length, hw);
@@ -3287,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);
@@ -3304,7 +3813,7 @@ COMMAND_HANDLER(handle_wp_command)
                struct watchpoint *watchpoint = target->watchpoints;
 
                while (watchpoint) {
-                       command_print(CMD_CTX, "address: 0x%8.8" PRIx32
+                       command_print(CMD_CTX, "address: " TARGET_ADDR_FMT
                                        ", len: 0x%8.8" PRIx32
                                        ", r/w/a: %i, value: 0x%8.8" PRIx32
                                        ", mask: 0x%8.8" PRIx32,
@@ -3389,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;
 }
@@ -3408,14 +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)
@@ -3426,18 +3933,18 @@ static void writeString(FILE *f, char *s)
 typedef unsigned char UNIT[2];  /* unit of profiling */
 
 /* Dump a gmon.out histogram file. */
-static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filename,
-               bool with_range, uint32_t start_address, uint32_t end_address)
+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);
@@ -3492,10 +3999,11 @@ static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filena
        }
 
        /* 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, numBuckets);       /* # of buckets */
-       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);
@@ -3533,29 +4041,32 @@ COMMAND_HANDLER(handle_profile_command)
 
        const uint32_t MAX_PROFILE_SAMPLE_NUM = 10000;
        uint32_t offset;
-       uint32_t num_of_sampels;
+       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;
        }
 
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], offset);
-
+       uint64_t timestart_ms = timeval_ms();
        /**
         * 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_sampels, offset);
+                               &num_of_samples, offset);
        if (retval != ERROR_OK) {
                free(samples);
                return retval;
        }
+       uint32_t duration_ms = timeval_ms() - timestart_ms;
 
-       assert(num_of_sampels <= MAX_PROFILE_SAMPLE_NUM);
+       assert(num_of_samples <= MAX_PROFILE_SAMPLE_NUM);
 
        retval = target_poll(target);
        if (retval != ERROR_OK) {
@@ -3585,8 +4096,8 @@ COMMAND_HANDLER(handle_profile_command)
                COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], end_address);
        }
 
-       write_gmon(samples, num_of_sampels, CMD_ARGV[1],
-                       with_range, start_address, 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);
@@ -3646,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;
 
@@ -3654,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);
@@ -3674,6 +4188,14 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc,
        len = l;
        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:
                        width = 1;
@@ -3716,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;
        }
 
@@ -3739,13 +4261,16 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc,
                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;
@@ -3767,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;
                }
        }
 
@@ -3834,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;
 
@@ -3842,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);
@@ -3862,6 +4390,14 @@ static int target_array2mem(Jim_Interp *interp, struct target *target,
        len = l;
        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:
                        width = 1;
@@ -3905,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;
        }
 
@@ -3948,18 +4484,22 @@ 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;
                        break;
                }
+               addr += count * width;
        }
 
        free(buffer);
@@ -3978,17 +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));
+
+                       /* Override current target by the target an event
+                        * is issued from (lot of scripts need it).
+                        * Return back to previous override as soon
+                        * as the handler processing is done */
+                       struct command_context *cmd_ctx = current_command_context(teap->interp);
+                       struct target *saved_target_override = cmd_ctx->current_target_override;
+                       cmd_ctx->current_target_override = target;
+
                        if (Jim_EvalObj(teap->interp, teap->body) != JIM_OK) {
                                Jim_MakeErrorMessage(teap->interp);
                                command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(teap->interp), NULL));
                        }
+
+                       cmd_ctx->current_target_override = saved_target_override;
                }
        }
 }
@@ -4015,11 +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[] = {
@@ -4030,11 +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 }
 };
 
@@ -4043,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 ... */
@@ -4252,28 +4804,6 @@ no_params:
                        /* 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);
-                               if (e != JIM_OK)
-                                       return e;
-                               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);
@@ -4292,6 +4822,13 @@ no_params:
                        if (goi->isconfigure) {
                                Jim_Obj *o_t;
                                struct jtag_tap *tap;
+
+                               if (target->has_dap) {
+                                       Jim_SetResultString(goi->interp,
+                                               "target requires -dap parameter instead of -chain-position!", -1);
+                                       return JIM_ERR;
+                               }
+
                                target_free_all_working_areas(target);
                                e = Jim_GetOpt_Obj(goi, &o_t);
                                if (e != JIM_OK)
@@ -4299,8 +4836,8 @@ no_params:
                                tap = jtag_tap_by_jim_obj(goi->interp, o_t);
                                if (tap == NULL)
                                        return JIM_ERR;
-                               /* make this exactly 1 or 0 */
                                target->tap = tap;
+                               target->tap_configured = true;
                        } else {
                                if (goi->argc != 0)
                                        goto no_params;
@@ -4322,7 +4859,6 @@ no_params:
                        Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
                        /* loop for more */
                        break;
-
                case TCFG_RTOS:
                        /* RTOS */
                        {
@@ -4332,6 +4868,27 @@ no_params:
                        }
                        /* loop for more */
                        break;
+
+               case TCFG_DEFER_EXAMINE:
+                       /* DEFER_EXAMINE */
+                       target->defer_examine = true;
+                       /* loop for more */
+                       break;
+
+               case TCFG_GDB_PORT:
+                       if (goi->isconfigure) {
+                               const char *s;
+                               e = Jim_GetOpt_String(goi, &s, NULL);
+                               if (e != JIM_OK)
+                                       return e;
+                               target->gdb_port_override = strdup(s);
+                       } else {
+                               if (goi->argc != 0)
+                                       goto no_params;
+                       }
+                       Jim_SetResultString(goi->interp, target->gdb_port_override ? : "undefined", -1);
+                       /* loop for more */
+                       break;
                }
        } /* while (goi->argc) */
 
@@ -4346,12 +4903,9 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a
 
        Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
        goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure");
-       int need_args = 1 + goi.isconfigure;
-       if (goi.argc < need_args) {
+       if (goi.argc < 1) {
                Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
-                       goi.isconfigure
-                               ? "missing: -option VALUE ..."
-                               : "missing: -option ...");
+                                "missing: -option ...");
                return JIM_ERR;
        }
        struct target *target = Jim_CmdPrivData(goi.interp);
@@ -4464,7 +5018,7 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        }
 
        int (*fn)(struct target *target,
-                       uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
+                       target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer);
        fn = target_read_memory;
 
        int e;
@@ -4602,20 +5156,58 @@ static int jim_target_tap_disabled(Jim_Interp *interp)
 
 static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
-       if (argc != 1) {
-               Jim_WrongNumArgs(interp, 1, argv, "[no parameters]");
+       bool allow_defer = false;
+
+       Jim_GetOptInfo goi;
+       Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
+       if (goi.argc > 1) {
+               const char *cmd_name = Jim_GetString(argv[0], NULL);
+               Jim_SetResultFormatted(goi.interp,
+                               "usage: %s ['allow-defer']", cmd_name);
                return JIM_ERR;
        }
+       if (goi.argc > 0 &&
+           strcmp(Jim_GetString(argv[1], NULL), "allow-defer") == 0) {
+               /* consume it */
+               struct Jim_Obj *obj;
+               int e = Jim_GetOpt_Obj(&goi, &obj);
+               if (e != JIM_OK)
+                       return e;
+               allow_defer = true;
+       }
+
        struct target *target = Jim_CmdPrivData(interp);
        if (!target->tap->enabled)
                return jim_target_tap_disabled(interp);
 
+       if (allow_defer && target->defer_examine) {
+               LOG_INFO("Deferring arp_examine of %s", target_name(target));
+               LOG_INFO("Use arp_examine command to examine it manually!");
+               return JIM_OK;
+       }
+
        int e = target->type->examine(target);
        if (e != ERROR_OK)
                return JIM_ERR;
        return JIM_OK;
 }
 
+static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+{
+       struct target *target = Jim_CmdPrivData(interp);
+
+       Jim_SetResultBool(interp, target_was_examined(target));
+       return JIM_OK;
+}
+
+static int jim_target_examine_deferred(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
+{
+       struct target *target = Jim_CmdPrivData(interp);
+
+       Jim_SetResultBool(interp, target->defer_examine);
+       return JIM_OK;
+}
+
 static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
        if (argc != 1) {
@@ -4676,16 +5268,17 @@ 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) {
                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. */
@@ -4896,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",
@@ -4942,7 +5548,6 @@ 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;
@@ -4967,10 +5572,18 @@ static int target_create(Jim_GetOptInfo *goi)
        }
 
        /* TYPE */
-       e = Jim_GetOpt_String(goi, &cp2, NULL);
+       e = Jim_GetOpt_String(goi, &cp, NULL);
        if (e != JIM_OK)
                return e;
-       cp = cp2;
+       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)) {
@@ -5009,9 +5622,10 @@ static int target_create(Jim_GetOptInfo *goi)
        target = calloc(1, sizeof(struct target));
        /* set target number */
        target->target_number = new_target_number();
+       cmd_ctx->current_target = target;
 
        /* 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));
 
@@ -5034,19 +5648,12 @@ static int target_create(Jim_GetOptInfo *goi)
        target->next                = NULL;
        target->arch_info           = NULL;
 
-       target->display             = 1;
+       target->verbose_halt_msg        = true;
 
        target->halt_issued                     = false;
 
        /* initialize trace information */
-       target->trace_info = malloc(sizeof(struct trace));
-       target->trace_info->num_trace_points         = 0;
-       target->trace_info->trace_points_size        = 0;
-       target->trace_info->trace_points             = NULL;
-       target->trace_info->trace_history_size       = 0;
-       target->trace_info->trace_history            = NULL;
-       target->trace_info->trace_history_pos        = 0;
-       target->trace_info->trace_history_overflowed = 0;
+       target->trace_info = calloc(1, sizeof(struct trace));
 
        target->dbgmsg          = NULL;
        target->dbg_msg_enabled = 0;
@@ -5056,16 +5663,31 @@ static int target_create(Jim_GetOptInfo *goi)
        target->rtos = NULL;
        target->rtos_auto_detect = false;
 
+       target->gdb_port_override = NULL;
+
        /* Do the rest as "configure" options */
        goi->isconfigure = 1;
        e = target_configure(goi, target);
 
-       if (target->tap == NULL) {
-               Jim_SetResultString(goi->interp, "-chain-position required when creating target", -1);
-               e = JIM_ERR;
+       if (e == JIM_OK) {
+               if (target->has_dap) {
+                       if (!target->dap_configured) {
+                               Jim_SetResultString(goi->interp, "-dap ?name? required when creating target", -1);
+                               e = JIM_ERR;
+                       }
+               } else {
+                       if (!target->tap_configured) {
+                               Jim_SetResultString(goi->interp, "-chain-position ?name? required when creating target", -1);
+                               e = JIM_ERR;
+                       }
+               }
+               /* tap must be set after target was configured */
+               if (target->tap == NULL)
+                       e = JIM_ERR;
        }
 
        if (e != JIM_OK) {
+               free(target->gdb_port_override);
                free(target->type);
                free(target);
                return e;
@@ -5076,21 +5698,27 @@ 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 */
        {
@@ -5239,55 +5867,6 @@ static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        return target_create(&goi);
 }
 
-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);
-
-       /* 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;
-       }
-       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;
-
-               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;
-}
-
-static int jim_target_count(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
-       if (argc != 1) {
-               Jim_WrongNumArgs(interp, 1, argv, "<no parameters>");
-               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;
-}
-
 static const struct command_registration target_subcommand_handlers[] = {
        {
                .name = "init",
@@ -5297,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",
@@ -5323,21 +5901,6 @@ static const struct command_registration target_subcommand_handlers[] = {
                .help = "Returns the names of all targets as a list of strings",
        },
        {
-               .name = "number",
-               .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)",
-       },
-       {
                .name = "smp",
                .mode = COMMAND_ANY,
                .jim_handler = jim_target_smp,
@@ -5349,7 +5912,7 @@ static const struct command_registration target_subcommand_handlers[] = {
 };
 
 struct FastLoad {
-       uint32_t address;
+       target_addr_t address;
        uint8_t *data;
        int length;
 
@@ -5376,8 +5939,8 @@ COMMAND_HANDLER(handle_fast_load_image_command)
        uint8_t *buffer;
        size_t buf_cnt;
        uint32_t image_size;
-       uint32_t min_address = 0;
-       uint32_t max_address = 0xffffffff;
+       target_addr_t min_address = 0;
+       target_addr_t max_address = -1;
        int i;
 
        struct image image;
@@ -5397,7 +5960,7 @@ COMMAND_HANDLER(handle_fast_load_image_command)
        image_size = 0x0;
        retval = ERROR_OK;
        fastload_num = image.num_sections;
-       fastload = (struct FastLoad *)malloc(sizeof(struct FastLoad)*image.num_sections);
+       fastload = malloc(sizeof(struct FastLoad)*image.num_sections);
        if (fastload == NULL) {
                command_print(CMD_CTX, "out of memory");
                image_close(&image);
@@ -5483,7 +6046,7 @@ COMMAND_HANDLER(handle_fast_load_command)
                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++) {
@@ -5497,7 +6060,7 @@ COMMAND_HANDLER(handle_fast_load_command)
                size += fastload[i].length;
        }
        if (retval == ERROR_OK) {
-               int after = timeval_ms();
+               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;
@@ -5562,6 +6125,198 @@ COMMAND_HANDLER(handle_ps_command)
        }
 }
 
+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",
@@ -5599,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",
@@ -5656,6 +6411,13 @@ static const struct command_registration target_exec_command_handlers[] = {
                .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,
                .mode = COMMAND_EXEC,
@@ -5677,6 +6439,13 @@ static const struct command_registration target_exec_command_handlers[] = {
                .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,
                .mode = COMMAND_EXEC,
@@ -5702,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> [<asid>]<length> ['hw'|'hw_ctx']",
+               .usage = "<address> [<asid>] <length> ['hw'|'hw_ctx']",
        },
        {
                .name = "rbp",
@@ -5739,6 +6508,12 @@ static const struct command_registration target_exec_command_handlers[] = {
                .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,
                .mode = COMMAND_EXEC,
@@ -5781,6 +6556,13 @@ static const struct command_registration target_exec_command_handlers[] = {
                .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
 };