target/semihosting: export semihosting_common_handlers[] from header file
[fw/openocd] / src / target / armv4_5.c
index 5ee8ead66f757ec6d95ad5ec3d710f0fb4a6453d..2b347924fed12432b3b13c1207686873414b584b 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 /***************************************************************************
  *   Copyright (C) 2005 by Dominic Rath                                    *
  *   Dominic.Rath@gmx.de                                                   *
  *                                                                         *
  *   Copyright (C) 2018 by Liviu Ionescu                                   *
  *   <ilg@livius.net>                                                      *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   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, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -48,6 +37,7 @@ enum {
        ARMV4_5_SPSR_ABT = 35,
        ARMV4_5_SPSR_UND = 36,
        ARM_SPSR_MON = 41,
+       ARM_SPSR_HYP = 43,
 };
 
 static const uint8_t arm_usr_indices[17] = {
@@ -78,6 +68,10 @@ static const uint8_t arm_mon_indices[3] = {
        39, 40, ARM_SPSR_MON,
 };
 
+static const uint8_t arm_hyp_indices[2] = {
+       42, ARM_SPSR_HYP,
+};
+
 static const struct {
        const char *name;
        unsigned short psr;
@@ -163,6 +157,14 @@ static const struct {
                .name = "Handler",
                .psr = ARM_MODE_HANDLER,
        },
+
+       /* armv7-a with virtualization extension */
+       {
+               .name = "Hypervisor",
+               .psr = ARM_MODE_HYP,
+               .n_indices = ARRAY_SIZE(arm_hyp_indices),
+               .indices = arm_hyp_indices,
+       },
 };
 
 /** Map PSR mode bits to the name of an ARM processor operating mode. */
@@ -209,6 +211,8 @@ int arm_mode_to_number(enum arm_mode mode)
                case ARM_MODE_MON:
                case ARM_MODE_1176_MON:
                        return 7;
+               case ARM_MODE_HYP:
+                       return 8;
                default:
                        LOG_ERROR("invalid mode value encountered %d", mode);
                        return -1;
@@ -235,6 +239,8 @@ enum arm_mode armv4_5_number_to_mode(int number)
                        return ARM_MODE_SYS;
                case 7:
                        return ARM_MODE_MON;
+               case 8:
+                       return ARM_MODE_HYP;
                default:
                        LOG_ERROR("mode index out of bounds %d", number);
                        return ARM_MODE_ANY;
@@ -274,24 +280,24 @@ static const struct {
         * correspond to r0..r7, and the fifteenth to PC, so that callers
         * don't need to map them.
         */
-       { .name = "r0", .cookie = 0, .mode = ARM_MODE_ANY, .gdb_index = 0, },
-       { .name = "r1", .cookie = 1, .mode = ARM_MODE_ANY, .gdb_index = 1, },
-       { .name = "r2", .cookie = 2, .mode = ARM_MODE_ANY, .gdb_index = 2, },
-       { .name = "r3", .cookie = 3, .mode = ARM_MODE_ANY, .gdb_index = 3, },
-       { .name = "r4", .cookie = 4, .mode = ARM_MODE_ANY, .gdb_index = 4, },
-       { .name = "r5", .cookie = 5, .mode = ARM_MODE_ANY, .gdb_index = 5, },
-       { .name = "r6", .cookie = 6, .mode = ARM_MODE_ANY, .gdb_index = 6, },
-       { .name = "r7", .cookie = 7, .mode = ARM_MODE_ANY, .gdb_index = 7, },
+       [0] = { .name = "r0", .cookie = 0, .mode = ARM_MODE_ANY, .gdb_index = 0, },
+       [1] = { .name = "r1", .cookie = 1, .mode = ARM_MODE_ANY, .gdb_index = 1, },
+       [2] = { .name = "r2", .cookie = 2, .mode = ARM_MODE_ANY, .gdb_index = 2, },
+       [3] = { .name = "r3", .cookie = 3, .mode = ARM_MODE_ANY, .gdb_index = 3, },
+       [4] = { .name = "r4", .cookie = 4, .mode = ARM_MODE_ANY, .gdb_index = 4, },
+       [5] = { .name = "r5", .cookie = 5, .mode = ARM_MODE_ANY, .gdb_index = 5, },
+       [6] = { .name = "r6", .cookie = 6, .mode = ARM_MODE_ANY, .gdb_index = 6, },
+       [7] = { .name = "r7", .cookie = 7, .mode = ARM_MODE_ANY, .gdb_index = 7, },
 
        /* NOTE: regs 8..12 might be shadowed by FIQ ... flagging
         * them as MODE_ANY creates special cases.  (ANY means
         * "not mapped" elsewhere; here it's "everything but FIQ".)
         */
-       { .name = "r8", .cookie = 8, .mode = ARM_MODE_ANY, .gdb_index = 8, },
-       { .name = "r9", .cookie = 9, .mode = ARM_MODE_ANY, .gdb_index = 9, },
-       { .name = "r10", .cookie = 10, .mode = ARM_MODE_ANY, .gdb_index = 10, },
-       { .name = "r11", .cookie = 11, .mode = ARM_MODE_ANY, .gdb_index = 11, },
-       { .name = "r12", .cookie = 12, .mode = ARM_MODE_ANY, .gdb_index = 12, },
+       [8] = { .name = "r8", .cookie = 8, .mode = ARM_MODE_ANY, .gdb_index = 8, },
+       [9] = { .name = "r9", .cookie = 9, .mode = ARM_MODE_ANY, .gdb_index = 9, },
+       [10] = { .name = "r10", .cookie = 10, .mode = ARM_MODE_ANY, .gdb_index = 10, },
+       [11] = { .name = "r11", .cookie = 11, .mode = ARM_MODE_ANY, .gdb_index = 11, },
+       [12] = { .name = "r12", .cookie = 12, .mode = ARM_MODE_ANY, .gdb_index = 12, },
 
        /* Historical GDB mapping of indices:
         *  - 13-14 are sp and lr, but banked counterparts are used
@@ -300,48 +306,51 @@ static const struct {
         */
 
        /* NOTE all MODE_USR registers are equivalent to MODE_SYS ones */
-       { .name = "sp_usr", .cookie = 13, .mode = ARM_MODE_USR, .gdb_index = 26, },
-       { .name = "lr_usr", .cookie = 14, .mode = ARM_MODE_USR, .gdb_index = 27, },
+       [13] = { .name = "sp_usr", .cookie = 13, .mode = ARM_MODE_USR, .gdb_index = 26, },
+       [14] = { .name = "lr_usr", .cookie = 14, .mode = ARM_MODE_USR, .gdb_index = 27, },
 
        /* guaranteed to be at index 15 */
-       { .name = "pc", .cookie = 15, .mode = ARM_MODE_ANY, .gdb_index = 15, },
-       { .name = "r8_fiq", .cookie = 8, .mode = ARM_MODE_FIQ, .gdb_index = 28, },
-       { .name = "r9_fiq", .cookie = 9, .mode = ARM_MODE_FIQ, .gdb_index = 29, },
-       { .name = "r10_fiq", .cookie = 10, .mode = ARM_MODE_FIQ, .gdb_index = 30, },
-       { .name = "r11_fiq", .cookie = 11, .mode = ARM_MODE_FIQ, .gdb_index = 31, },
-       { .name = "r12_fiq", .cookie = 12, .mode = ARM_MODE_FIQ, .gdb_index = 32, },
+       [15] = { .name = "pc", .cookie = 15, .mode = ARM_MODE_ANY, .gdb_index = 15, },
+       [16] = { .name = "r8_fiq", .cookie = 8, .mode = ARM_MODE_FIQ, .gdb_index = 28, },
+       [17] = { .name = "r9_fiq", .cookie = 9, .mode = ARM_MODE_FIQ, .gdb_index = 29, },
+       [18] = { .name = "r10_fiq", .cookie = 10, .mode = ARM_MODE_FIQ, .gdb_index = 30, },
+       [19] = { .name = "r11_fiq", .cookie = 11, .mode = ARM_MODE_FIQ, .gdb_index = 31, },
+       [20] = { .name = "r12_fiq", .cookie = 12, .mode = ARM_MODE_FIQ, .gdb_index = 32, },
 
-       { .name = "sp_fiq", .cookie = 13, .mode = ARM_MODE_FIQ, .gdb_index = 33, },
-       { .name = "lr_fiq", .cookie = 14, .mode = ARM_MODE_FIQ, .gdb_index = 34, },
+       [21] = { .name = "sp_fiq", .cookie = 13, .mode = ARM_MODE_FIQ, .gdb_index = 33, },
+       [22] = { .name = "lr_fiq", .cookie = 14, .mode = ARM_MODE_FIQ, .gdb_index = 34, },
 
-       { .name = "sp_irq", .cookie = 13, .mode = ARM_MODE_IRQ, .gdb_index = 35, },
-       { .name = "lr_irq", .cookie = 14, .mode = ARM_MODE_IRQ, .gdb_index = 36, },
+       [23] = { .name = "sp_irq", .cookie = 13, .mode = ARM_MODE_IRQ, .gdb_index = 35, },
+       [24] = { .name = "lr_irq", .cookie = 14, .mode = ARM_MODE_IRQ, .gdb_index = 36, },
 
-       { .name = "sp_svc", .cookie = 13, .mode = ARM_MODE_SVC, .gdb_index = 37, },
-       { .name = "lr_svc", .cookie = 14, .mode = ARM_MODE_SVC, .gdb_index = 38, },
+       [25] = { .name = "sp_svc", .cookie = 13, .mode = ARM_MODE_SVC, .gdb_index = 37, },
+       [26] = { .name = "lr_svc", .cookie = 14, .mode = ARM_MODE_SVC, .gdb_index = 38, },
 
-       { .name = "sp_abt", .cookie = 13, .mode = ARM_MODE_ABT, .gdb_index = 39, },
-       { .name = "lr_abt", .cookie = 14, .mode = ARM_MODE_ABT, .gdb_index = 40, },
+       [27] = { .name = "sp_abt", .cookie = 13, .mode = ARM_MODE_ABT, .gdb_index = 39, },
+       [28] = { .name = "lr_abt", .cookie = 14, .mode = ARM_MODE_ABT, .gdb_index = 40, },
 
-       { .name = "sp_und", .cookie = 13, .mode = ARM_MODE_UND, .gdb_index = 41, },
-       { .name = "lr_und", .cookie = 14, .mode = ARM_MODE_UND, .gdb_index = 42, },
+       [29] = { .name = "sp_und", .cookie = 13, .mode = ARM_MODE_UND, .gdb_index = 41, },
+       [30] = { .name = "lr_und", .cookie = 14, .mode = ARM_MODE_UND, .gdb_index = 42, },
 
-       { .name = "cpsr", .cookie = 16, .mode = ARM_MODE_ANY, .gdb_index = 25, },
-       { .name = "spsr_fiq", .cookie = 16, .mode = ARM_MODE_FIQ, .gdb_index = 43, },
-       { .name = "spsr_irq", .cookie = 16, .mode = ARM_MODE_IRQ, .gdb_index = 44, },
-       { .name = "spsr_svc", .cookie = 16, .mode = ARM_MODE_SVC, .gdb_index = 45, },
-       { .name = "spsr_abt", .cookie = 16, .mode = ARM_MODE_ABT, .gdb_index = 46, },
-       { .name = "spsr_und", .cookie = 16, .mode = ARM_MODE_UND, .gdb_index = 47, },
+       [31] = { .name = "cpsr", .cookie = 16, .mode = ARM_MODE_ANY, .gdb_index = 25, },
+       [32] = { .name = "spsr_fiq", .cookie = 16, .mode = ARM_MODE_FIQ, .gdb_index = 43, },
+       [33] = { .name = "spsr_irq", .cookie = 16, .mode = ARM_MODE_IRQ, .gdb_index = 44, },
+       [34] = { .name = "spsr_svc", .cookie = 16, .mode = ARM_MODE_SVC, .gdb_index = 45, },
+       [35] = { .name = "spsr_abt", .cookie = 16, .mode = ARM_MODE_ABT, .gdb_index = 46, },
+       [36] = { .name = "spsr_und", .cookie = 16, .mode = ARM_MODE_UND, .gdb_index = 47, },
 
        /* These are only used for GDB target description, banked registers are accessed instead */
-       { .name = "sp", .cookie = 13, .mode = ARM_MODE_ANY, .gdb_index = 13, },
-       { .name = "lr", .cookie = 14, .mode = ARM_MODE_ANY, .gdb_index = 14, },
+       [37] = { .name = "sp", .cookie = 13, .mode = ARM_MODE_ANY, .gdb_index = 13, },
+       [38] = { .name = "lr", .cookie = 14, .mode = ARM_MODE_ANY, .gdb_index = 14, },
 
        /* These exist only when the Security Extension (TrustZone) is present */
-       { .name = "sp_mon", .cookie = 13, .mode = ARM_MODE_MON, .gdb_index = 48, },
-       { .name = "lr_mon", .cookie = 14, .mode = ARM_MODE_MON, .gdb_index = 49, },
-       { .name = "spsr_mon", .cookie = 16, .mode = ARM_MODE_MON, .gdb_index = 50, },
+       [39] = { .name = "sp_mon", .cookie = 13, .mode = ARM_MODE_MON, .gdb_index = 48, },
+       [40] = { .name = "lr_mon", .cookie = 14, .mode = ARM_MODE_MON, .gdb_index = 49, },
+       [41] = { .name = "spsr_mon", .cookie = 16, .mode = ARM_MODE_MON, .gdb_index = 50, },
 
+       /* These exist only when the Virtualization Extensions is present */
+       [42] = { .name = "sp_hyp", .cookie = 13, .mode = ARM_MODE_HYP, .gdb_index = 51, },
+       [43] = { .name = "spsr_hyp", .cookie = 16, .mode = ARM_MODE_HYP, .gdb_index = 52, },
 };
 
 static const struct {
@@ -391,7 +400,7 @@ static const struct {
 /* map core mode (USR, FIQ, ...) and register number to
  * indices into the register cache
  */
-const int armv4_5_core_reg_map[8][17] = {
+const int armv4_5_core_reg_map[9][17] = {
        {       /* USR */
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
        },
@@ -414,7 +423,10 @@ const int armv4_5_core_reg_map[8][17] = {
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
        },
        {       /* MON */
-               0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 37, 38, 15, 39,
+               0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 39, 40, 15, 41,
+       },
+       {       /* HYP */
+               0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 42, 14, 15, 43,
        }
 };
 
@@ -434,8 +446,8 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr)
         */
        if (arm->cpsr) {
                buf_set_u32(arm->cpsr->value, 0, 32, cpsr);
-               arm->cpsr->valid = 1;
-               arm->cpsr->dirty = 0;
+               arm->cpsr->valid = true;
+               arm->cpsr->dirty = false;
        }
 
        arm->core_mode = mode;
@@ -526,7 +538,7 @@ static struct reg_feature arm_gdb_dummy_fp_features = {
 struct reg arm_gdb_dummy_fp_reg = {
        .name = "GDB dummy FPA register",
        .value = (uint8_t *) arm_gdb_dummy_fp_value,
-       .valid = 1,
+       .valid = true,
        .size = 96,
        .exist = false,
        .number = 16,
@@ -543,7 +555,7 @@ static const uint8_t arm_gdb_dummy_fps_value[4];
 struct reg arm_gdb_dummy_fps_reg = {
        .name = "GDB dummy FPA status register",
        .value = (uint8_t *) arm_gdb_dummy_fps_value,
-       .valid = 1,
+       .valid = true,
        .size = 32,
        .exist = false,
        .number = 24,
@@ -573,8 +585,8 @@ static int armv4_5_get_core_reg(struct reg *reg)
        retval = reg_arch_info->arm->read_core_reg(target, reg,
                        reg_arch_info->num, reg_arch_info->mode);
        if (retval == ERROR_OK) {
-               reg->valid = 1;
-               reg->dirty = 0;
+               reg->valid = true;
+               reg->dirty = false;
        }
 
        return retval;
@@ -619,9 +631,9 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
                        value = buf_get_u32(buf + 4, 0, 32);
                        buf_set_u32(reg->value + 4, 0, 32, value);
                }
-               reg->valid = 1;
+               reg->valid = true;
        }
-       reg->dirty = 1;
+       reg->dirty = true;
 
        return ERROR_OK;
 }
@@ -658,7 +670,11 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm)
        for (i = 0; i < num_core_regs; i++) {
                /* Skip registers this core doesn't expose */
                if (arm_core_regs[i].mode == ARM_MODE_MON
-                       && arm->core_type != ARM_MODE_MON)
+                       && arm->core_type != ARM_CORE_TYPE_SEC_EXT
+                       && arm->core_type != ARM_CORE_TYPE_VIRT_EXT)
+                       continue;
+               if (arm_core_regs[i].mode == ARM_MODE_HYP
+                       && arm->core_type != ARM_CORE_TYPE_VIRT_EXT)
                        continue;
 
                /* REVISIT handle Cortex-M, which only shadows R13/SP */
@@ -742,6 +758,27 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm)
        return cache;
 }
 
+void arm_free_reg_cache(struct arm *arm)
+{
+       if (!arm || !arm->core_cache)
+               return;
+
+       struct reg_cache *cache = arm->core_cache;
+
+       for (unsigned int i = 0; i < cache->num_regs; i++) {
+               struct reg *reg = &cache->reg_list[i];
+
+               free(reg->feature);
+               free(reg->reg_data_type);
+       }
+
+       free(cache->reg_list[0].arch_info);
+       free(cache->reg_list);
+       free(cache);
+
+       arm->core_cache = NULL;
+}
+
 int arm_arch_state(struct target *target)
 {
        struct arm *arm = target_to_arm(target);
@@ -752,7 +789,7 @@ int arm_arch_state(struct target *target)
        }
 
        /* avoid filling log waiting for fileio reply */
-       if (target->semihosting->hit_fileio)
+       if (target->semihosting && target->semihosting->hit_fileio)
                return ERROR_OK;
 
        LOG_USER("target halted in %s state due to %s, current mode: %s\n"
@@ -762,15 +799,12 @@ int arm_arch_state(struct target *target)
                arm_mode_name(arm->core_mode),
                buf_get_u32(arm->cpsr->value, 0, 32),
                buf_get_u32(arm->pc->value, 0, 32),
-               target->semihosting->is_active ? ", semihosting" : "",
-               target->semihosting->is_fileio ? " fileio" : "");
+               (target->semihosting && target->semihosting->is_active) ? ", semihosting" : "",
+               (target->semihosting && target->semihosting->is_fileio) ? " fileio" : "");
 
        return ERROR_OK;
 }
 
-#define ARMV4_5_CORE_REG_MODENUM(cache, mode, num) \
-       (cache->reg_list[armv4_5_core_reg_map[mode][num]])
-
 COMMAND_HANDLER(handle_armv4_5_reg_command)
 {
        struct target *target = get_current_target(CMD_CTX);
@@ -778,17 +812,17 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
        struct reg *regs;
 
        if (!is_arm(arm)) {
-               command_print(CMD_CTX, "current target isn't an ARM");
+               command_print(CMD, "current target isn't an ARM");
                return ERROR_FAIL;
        }
 
        if (target->state != TARGET_HALTED) {
-               command_print(CMD_CTX, "error: target must be halted for register accesses");
+               command_print(CMD, "error: target must be halted for register accesses");
                return ERROR_FAIL;
        }
 
-       if (arm->core_type != ARM_MODE_ANY) {
-               command_print(CMD_CTX,
+       if (arm->core_type != ARM_CORE_TYPE_STD) {
+               command_print(CMD,
                        "Microcontroller Profile not supported - use standard reg cmd");
                return ERROR_OK;
        }
@@ -799,7 +833,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
        }
 
        if (!arm->full_context) {
-               command_print(CMD_CTX, "error: target doesn't support %s",
+               command_print(CMD, "error: target doesn't support %s",
                        CMD_NAME);
                return ERROR_FAIL;
        }
@@ -811,6 +845,9 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
                char *sep = "\n";
                char *shadow = "";
 
+               if (!arm_mode_data[mode].n_indices)
+                       continue;
+
                /* label this bank of registers (or shadows) */
                switch (arm_mode_data[mode].psr) {
                        case ARM_MODE_SYS:
@@ -819,8 +856,14 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
                                name = "System and User";
                                sep = "";
                                break;
+                       case ARM_MODE_HYP:
+                               if (arm->core_type != ARM_CORE_TYPE_VIRT_EXT)
+                                       continue;
+                       /* FALLTHROUGH */
                        case ARM_MODE_MON:
-                               if (arm->core_type != ARM_MODE_MON)
+                       case ARM_MODE_1176_MON:
+                               if (arm->core_type != ARM_CORE_TYPE_SEC_EXT
+                                       && arm->core_type != ARM_CORE_TYPE_VIRT_EXT)
                                        continue;
                        /* FALLTHROUGH */
                        default:
@@ -828,7 +871,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
                                shadow = "shadow ";
                                break;
                }
-               command_print(CMD_CTX, "%s%s mode %sregisters",
+               command_print(CMD, "%s%s mode %sregisters",
                        sep, name, shadow);
 
                /* display N rows of up to 4 registers each */
@@ -855,7 +898,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
                                                "%8s: %8.8" PRIx32 " ",
                                                reg->name, value);
                        }
-                       command_print(CMD_CTX, "%s", output);
+                       command_print(CMD, "%s", output);
                }
        }
 
@@ -868,13 +911,13 @@ COMMAND_HANDLER(handle_armv4_5_core_state_command)
        struct arm *arm = target_to_arm(target);
 
        if (!is_arm(arm)) {
-               command_print(CMD_CTX, "current target isn't an ARM");
+               command_print(CMD, "current target isn't an ARM");
                return ERROR_FAIL;
        }
 
-       if (arm->core_type == ARM_MODE_THREAD) {
+       if (arm->core_type == ARM_CORE_TYPE_M_PROFILE) {
                /* armv7m not supported */
-               command_print(CMD_CTX, "Unsupported Command");
+               command_print(CMD, "Unsupported Command");
                return ERROR_OK;
        }
 
@@ -885,89 +928,64 @@ COMMAND_HANDLER(handle_armv4_5_core_state_command)
                        arm->core_state = ARM_STATE_THUMB;
        }
 
-       command_print(CMD_CTX, "core state: %s", arm_state_strings[arm->core_state]);
+       command_print(CMD, "core state: %s", arm_state_strings[arm->core_state]);
 
        return ERROR_OK;
 }
 
 COMMAND_HANDLER(handle_arm_disassemble_command)
 {
-       int retval = ERROR_OK;
+#if HAVE_CAPSTONE
        struct target *target = get_current_target(CMD_CTX);
 
-       if (target == NULL) {
+       if (!target) {
                LOG_ERROR("No target selected");
                return ERROR_FAIL;
        }
 
        struct arm *arm = target_to_arm(target);
        target_addr_t address;
-       int count = 1;
-       int thumb = 0;
+       unsigned int count = 1;
+       bool thumb = false;
 
        if (!is_arm(arm)) {
-               command_print(CMD_CTX, "current target isn't an ARM");
+               command_print(CMD, "current target isn't an ARM");
                return ERROR_FAIL;
        }
 
-       if (arm->core_type == ARM_MODE_THREAD) {
+       if (arm->core_type == ARM_CORE_TYPE_M_PROFILE) {
                /* armv7m is always thumb mode */
-               thumb = 1;
+               thumb = true;
        }
 
        switch (CMD_ARGC) {
                case 3:
                        if (strcmp(CMD_ARGV[2], "thumb") != 0)
-                               goto usage;
-                       thumb = 1;
+                               return ERROR_COMMAND_SYNTAX_ERROR;
+                       thumb = true;
                /* FALL THROUGH */
                case 2:
-                       COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count);
+                       COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count);
                /* FALL THROUGH */
                case 1:
                        COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
                        if (address & 0x01) {
                                if (!thumb) {
-                                       command_print(CMD_CTX, "Disassemble as Thumb");
-                                       thumb = 1;
+                                       command_print(CMD, "Disassemble as Thumb");
+                                       thumb = true;
                                }
                                address &= ~1;
                        }
                        break;
                default:
-usage:
-                       count = 0;
-                       retval = ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
-       while (count-- > 0) {
-               struct arm_instruction cur_instruction;
-
-               if (thumb) {
-                       /* Always use Thumb2 disassembly for best handling
-                        * of 32-bit BL/BLX, and to work with newer cores
-                        * (some ARMv6, all ARMv7) that use Thumb2.
-                        */
-                       retval = thumb2_opcode(target, address,
-                                       &cur_instruction);
-                       if (retval != ERROR_OK)
-                               break;
-               } else {
-                       uint32_t opcode;
-
-                       retval = target_read_u32(target, address, &opcode);
-                       if (retval != ERROR_OK)
-                               break;
-                       retval = arm_evaluate_opcode(opcode, address,
-                                       &cur_instruction) != ERROR_OK;
-                       if (retval != ERROR_OK)
-                               break;
-               }
-               command_print(CMD_CTX, "%s", cur_instruction.text);
-               address += cur_instruction.instruction_size;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       return retval;
+       return arm_disassemble(CMD, target, address, count, thumb);
+#else
+       command_print(CMD, "capstone disassembly framework required");
+       return ERROR_FAIL;
+#endif
 }
 
 static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
@@ -978,10 +996,10 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
        int retval;
 
        context = current_command_context(interp);
-       assert(context != NULL);
+       assert(context);
 
        target = get_current_target(context);
-       if (target == NULL) {
+       if (!target) {
                LOG_ERROR("%s: no current target", __func__);
                return JIM_ERR;
        }
@@ -1004,8 +1022,8 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
        int cpnum;
        uint32_t op1;
        uint32_t op2;
-       uint32_t CRn;
-       uint32_t CRm;
+       uint32_t crn;
+       uint32_t crm;
        uint32_t value;
        long l;
 
@@ -1042,7 +1060,7 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
                        "CRn", (int) l);
                return JIM_ERR;
        }
-       CRn = l;
+       crn = l;
 
        retval = Jim_GetLong(interp, argv[4], &l);
        if (retval != JIM_OK)
@@ -1052,7 +1070,7 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
                        "CRm", (int) l);
                return JIM_ERR;
        }
-       CRm = l;
+       crm = l;
 
        retval = Jim_GetLong(interp, argv[5], &l);
        if (retval != JIM_OK)
@@ -1081,14 +1099,14 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
                value = l;
 
                /* NOTE: parameters reordered! */
-               /* ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2) */
-               retval = arm->mcr(target, cpnum, op1, op2, CRn, CRm, value);
+               /* ARMV4_5_MCR(cpnum, op1, 0, crn, crm, op2) */
+               retval = arm->mcr(target, cpnum, op1, op2, crn, crm, value);
                if (retval != ERROR_OK)
                        return JIM_ERR;
        } else {
                /* NOTE: parameters reordered! */
-               /* ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2) */
-               retval = arm->mrc(target, cpnum, op1, op2, CRn, CRm, &value);
+               /* ARMV4_5_MRC(cpnum, op1, 0, crn, crm, op2) */
+               retval = arm->mrc(target, cpnum, op1, op2, crn, crm, &value);
                if (retval != ERROR_OK)
                        return JIM_ERR;
 
@@ -1098,11 +1116,6 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
        return JIM_OK;
 }
 
-extern __COMMAND_HANDLER(handle_common_semihosting_command);
-extern __COMMAND_HANDLER(handle_common_semihosting_fileio_command);
-extern __COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command);
-extern __COMMAND_HANDLER(handle_common_semihosting_cmdline);
-
 static const struct command_registration arm_exec_command_handlers[] = {
        {
                .name = "reg",
@@ -1123,7 +1136,7 @@ static const struct command_registration arm_exec_command_handlers[] = {
                .handler = handle_arm_disassemble_command,
                .mode = COMMAND_EXEC,
                .usage = "address [count ['thumb']]",
-               .help = "disassemble instructions ",
+               .help = "disassemble instructions",
        },
        {
                .name = "mcr",
@@ -1134,37 +1147,13 @@ static const struct command_registration arm_exec_command_handlers[] = {
        },
        {
                .name = "mrc",
+               .mode = COMMAND_EXEC,
                .jim_handler = &jim_mcrmrc,
                .help = "read coprocessor register",
                .usage = "cpnum op1 CRn CRm op2",
        },
        {
-               "semihosting",
-               .handler = handle_common_semihosting_command,
-               .mode = COMMAND_EXEC,
-               .usage = "['enable'|'disable']",
-               .help = "activate support for semihosting operations",
-       },
-       {
-               "semihosting_cmdline",
-               .handler = handle_common_semihosting_cmdline,
-               .mode = COMMAND_EXEC,
-               .usage = "arguments",
-               .help = "command line arguments to be passed to program",
-       },
-       {
-               "semihosting_fileio",
-               .handler = handle_common_semihosting_fileio_command,
-               .mode = COMMAND_EXEC,
-               .usage = "['enable'|'disable']",
-               .help = "activate support for semihosting fileio operations",
-       },
-       {
-               "semihosting_resexit",
-               .handler = handle_common_semihosting_resumable_exit_command,
-               .mode = COMMAND_EXEC,
-               .usage = "['enable'|'disable']",
-               .help = "activate support for semihosting resumable exit",
+               .chain = semihosting_common_handlers,
        },
        COMMAND_REGISTRATION_DONE
 };
@@ -1179,6 +1168,20 @@ const struct command_registration arm_command_handlers[] = {
        COMMAND_REGISTRATION_DONE
 };
 
+/*
+ * gdb for arm targets (e.g. arm-none-eabi-gdb) supports several variants
+ * of arm architecture. You can list them using the autocompletion of gdb
+ * command prompt by typing "set architecture " and then press TAB key.
+ * The default, selected automatically, is "arm".
+ * Let's use the default value, here, to make gdb-multiarch behave in the
+ * same way as a gdb for arm. This can be changed later on. User can still
+ * set the specific architecture variant with the gdb command.
+ */
+const char *arm_get_gdb_arch(struct target *target)
+{
+       return "arm";
+}
+
 int arm_get_gdb_reg_list(struct target *target,
        struct reg **reg_list[], int *reg_list_size,
        enum target_register_class reg_class)
@@ -1207,10 +1210,18 @@ int arm_get_gdb_reg_list(struct target *target,
                (*reg_list)[25] = arm->cpsr;
 
                return ERROR_OK;
-               break;
 
        case REG_CLASS_ALL:
-               *reg_list_size = (arm->core_type != ARM_MODE_MON ? 48 : 51);
+               switch (arm->core_type) {
+                       case ARM_CORE_TYPE_SEC_EXT:
+                               *reg_list_size = 51;
+                               break;
+                       case ARM_CORE_TYPE_VIRT_EXT:
+                               *reg_list_size = 53;
+                               break;
+                       default:
+                               *reg_list_size = 48;
+               }
                unsigned int list_size_core = *reg_list_size;
                if (arm->arm_vfp_version == ARM_VFP_V3)
                        *reg_list_size += 33;
@@ -1222,9 +1233,15 @@ int arm_get_gdb_reg_list(struct target *target,
 
                for (i = 13; i < ARRAY_SIZE(arm_core_regs); i++) {
                                int reg_index = arm->core_cache->reg_list[i].number;
-                               if (!(arm_core_regs[i].mode == ARM_MODE_MON
-                                               && arm->core_type != ARM_MODE_MON))
-                                       (*reg_list)[reg_index] = &(arm->core_cache->reg_list[i]);
+
+                               if (arm_core_regs[i].mode == ARM_MODE_MON
+                                       && arm->core_type != ARM_CORE_TYPE_SEC_EXT
+                                       && arm->core_type != ARM_CORE_TYPE_VIRT_EXT)
+                                       continue;
+                               if (arm_core_regs[i].mode == ARM_MODE_HYP
+                                       && arm->core_type != ARM_CORE_TYPE_VIRT_EXT)
+                                       continue;
+                               (*reg_list)[reg_index] = &(arm->core_cache->reg_list[i]);
                }
 
                /* When we supply the target description, there is no need for fake FPA */
@@ -1242,12 +1259,10 @@ int arm_get_gdb_reg_list(struct target *target,
                }
 
                return ERROR_OK;
-               break;
 
        default:
                LOG_ERROR("not a valid register class type in query.");
                return ERROR_FAIL;
-               break;
        }
 }
 
@@ -1319,7 +1334,7 @@ int armv4_5_run_algorithm_inner(struct target *target,
        }
 
        /* armv5 and later can terminate with BKPT instruction; less overhead */
-       if (!exit_point && arm->is_armv4) {
+       if (!exit_point && arm->arch == ARM_ARCH_V4) {
                LOG_ERROR("ARMv4 target needs HW breakpoint location");
                return ERROR_FAIL;
        }
@@ -1340,6 +1355,8 @@ int armv4_5_run_algorithm_inner(struct target *target,
        cpsr = buf_get_u32(arm->cpsr->value, 0, 32);
 
        for (i = 0; i < num_mem_params; i++) {
+               if (mem_params[i].direction == PARAM_IN)
+                       continue;
                retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size,
                                mem_params[i].value);
                if (retval != ERROR_OK)
@@ -1347,7 +1364,10 @@ int armv4_5_run_algorithm_inner(struct target *target,
        }
 
        for (i = 0; i < num_reg_params; i++) {
-               struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, 0);
+               if (reg_params[i].direction == PARAM_IN)
+                       continue;
+
+               struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, false);
                if (!reg) {
                        LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
                        return ERROR_COMMAND_SYNTAX_ERROR;
@@ -1379,8 +1399,8 @@ int armv4_5_run_algorithm_inner(struct target *target,
                        arm_algorithm_info->core_mode);
                buf_set_u32(arm->cpsr->value, 0, 5,
                        arm_algorithm_info->core_mode);
-               arm->cpsr->dirty = 1;
-               arm->cpsr->valid = 1;
+               arm->cpsr->dirty = true;
+               arm->cpsr->valid = true;
        }
 
        /* terminate using a hardware or (ARMv5+) software breakpoint */
@@ -1419,7 +1439,7 @@ int armv4_5_run_algorithm_inner(struct target *target,
 
                        struct reg *reg = register_get_by_name(arm->core_cache,
                                        reg_params[i].reg_name,
-                                       0);
+                                       false);
                        if (!reg) {
                                LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
                                retval = ERROR_COMMAND_SYNTAX_ERROR;
@@ -1450,14 +1470,14 @@ int armv4_5_run_algorithm_inner(struct target *target,
                        buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
                                arm_algorithm_info->core_mode, i).value, 0, 32, context[i]);
                        ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode,
-                               i).valid = 1;
+                               i).valid = true;
                        ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode,
-                               i).dirty = 1;
+                               i).dirty = true;
                }
        }
 
        arm_set_cpsr(arm, cpsr);
-       arm->cpsr->dirty = 1;
+       arm->cpsr->dirty = true;
 
        arm->core_state = core_state;
 
@@ -1535,7 +1555,7 @@ int arm_checksum_memory(struct target *target,
        int timeout = 20000 * (1 + (count / (1024 * 1024)));
 
        /* armv4 must exit using a hardware breakpoint */
-       if (arm->is_armv4)
+       if (arm->arch == ARM_ARCH_V4)
                exit_var = crc_algorithm->address + sizeof(arm_crc_code_le) - 8;
 
        retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
@@ -1616,7 +1636,7 @@ int arm_blank_check_memory(struct target *target,
        buf_set_u32(reg_params[2].value, 0, 32, erased_value);
 
        /* armv4 must exit using a hardware breakpoint */
-       if (arm->is_armv4)
+       if (arm->arch == ARM_ARCH_V4)
                exit_var = check_algorithm->address + sizeof(check_code_le) - 4;
 
        retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
@@ -1648,7 +1668,7 @@ static int arm_full_context(struct target *target)
        int retval = ERROR_OK;
 
        for (; num_regs && retval == ERROR_OK; num_regs--, reg++) {
-               if (reg->valid)
+               if (!reg->exist || reg->valid)
                        continue;
                retval = armv4_5_get_core_reg(reg);
        }
@@ -1657,7 +1677,7 @@ static int arm_full_context(struct target *target)
 
 static int arm_default_mrc(struct target *target, int cpnum,
        uint32_t op1, uint32_t op2,
-       uint32_t CRn, uint32_t CRm,
+       uint32_t crn, uint32_t crm,
        uint32_t *value)
 {
        LOG_ERROR("%s doesn't implement MRC", target_type_name(target));
@@ -1666,7 +1686,7 @@ static int arm_default_mrc(struct target *target, int cpnum,
 
 static int arm_default_mcr(struct target *target, int cpnum,
        uint32_t op1, uint32_t op2,
-       uint32_t CRn, uint32_t CRm,
+       uint32_t crn, uint32_t crm,
        uint32_t value)
 {
        LOG_ERROR("%s doesn't implement MCR", target_type_name(target));
@@ -1681,8 +1701,8 @@ int arm_init_arch_info(struct target *target, struct arm *arm)
        arm->common_magic = ARM_COMMON_MAGIC;
 
        /* core_type may be overridden by subtype logic */
-       if (arm->core_type != ARM_MODE_THREAD) {
-               arm->core_type = ARM_MODE_ANY;
+       if (arm->core_type != ARM_CORE_TYPE_M_PROFILE) {
+               arm->core_type = ARM_CORE_TYPE_STD;
                arm_set_cpsr(arm, ARM_MODE_USR);
        }