jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / target / armv4_5.c
index 48050b078eba635261ebf87c2ad296f12e6326de..1886d5e1f6a612847402446d7dd40cfe44e2e12a 100644 (file)
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
 /***************************************************************************
  *   Copyright (C) 2005 by Dominic Rath                                    *
  *   Dominic.Rath@gmx.de                                                   *
@@ -8,18 +10,8 @@
  *   Copyright (C) 2008 by Oyvind Harboe                                   *
  *   oyvind.harboe@zylin.com                                               *
  *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (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/>. *
+ *   Copyright (C) 2018 by Liviu Ionescu                                   *
+ *   <ilg@livius.net>                                                      *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -34,6 +26,7 @@
 #include <helper/binarybuffer.h>
 #include "algorithm.h"
 #include "register.h"
+#include "semihosting_common.h"
 
 /* offsets into armv4_5 core register cache */
 enum {
@@ -44,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] = {
@@ -74,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;
@@ -159,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. */
@@ -205,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;
@@ -231,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;
@@ -270,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
@@ -296,54 +306,101 @@ 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 {
+       unsigned int id;
+       const char *name;
+       uint32_t bits;
+       enum arm_mode mode;
+       enum reg_type type;
+       const char *group;
+       const char *feature;
+} arm_vfp_v3_regs[] = {
+       { ARM_VFP_V3_D0,  "d0",  64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D1,  "d1",  64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D2,  "d2",  64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D3,  "d3",  64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D4,  "d4",  64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D5,  "d5",  64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D6,  "d6",  64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D7,  "d7",  64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D8,  "d8",  64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D9,  "d9",  64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D10, "d10", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D11, "d11", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D12, "d12", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D13, "d13", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D14, "d14", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D15, "d15", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D16, "d16", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D17, "d17", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D18, "d18", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D19, "d19", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D20, "d20", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D21, "d21", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D22, "d22", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D23, "d23", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D24, "d24", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D25, "d25", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D26, "d26", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D27, "d27", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D28, "d28", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D29, "d29", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D30, "d30", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_D31, "d31", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+       { ARM_VFP_V3_FPSCR, "fpscr", 32, ARM_MODE_ANY, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp"},
 };
 
 /* 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
        },
@@ -366,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,
        }
 };
 
@@ -386,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;
@@ -475,10 +535,10 @@ static struct reg_feature arm_gdb_dummy_fp_features = {
  * Modern ARM cores use Vector Floating Point (VFP), if they
  * have any floating point support.  VFP is not FPA-compatible.
  */
-struct reg arm_gdb_dummy_fp_reg = {
+static 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,
@@ -492,10 +552,10 @@ static const uint8_t arm_gdb_dummy_fps_value[4];
  * Dummy FPA status registers are required to support GDB on ARM.
  * Register packets require an obsolete FPA status register.
  */
-struct reg arm_gdb_dummy_fps_reg = {
+static 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,
@@ -518,15 +578,15 @@ static int armv4_5_get_core_reg(struct reg *reg)
        struct target *target = reg_arch_info->target;
 
        if (target->state != TARGET_HALTED) {
-               LOG_ERROR("Target not halted");
+               LOG_TARGET_ERROR(target, "not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
        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;
@@ -540,7 +600,7 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
        uint32_t value = buf_get_u32(buf, 0, 32);
 
        if (target->state != TARGET_HALTED) {
-               LOG_ERROR("Target not halted");
+               LOG_TARGET_ERROR(target, "not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -567,9 +627,13 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
                }
        } else {
                buf_set_u32(reg->value, 0, 32, value);
-               reg->valid = 1;
+               if (reg->size == 64) {
+                       value = buf_get_u32(buf + 4, 0, 32);
+                       buf_set_u32(reg->value + 4, 0, 32, value);
+               }
+               reg->valid = true;
        }
-       reg->dirty = 1;
+       reg->dirty = true;
 
        return ERROR_OK;
 }
@@ -582,6 +646,10 @@ static const struct reg_arch_type arm_reg_type = {
 struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm)
 {
        int num_regs = ARRAY_SIZE(arm_core_regs);
+       int num_core_regs = num_regs;
+       if (arm->arm_vfp_version == ARM_VFP_V3)
+               num_regs += ARRAY_SIZE(arm_vfp_v3_regs);
+
        struct reg_cache *cache = malloc(sizeof(struct reg_cache));
        struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
        struct arm_reg *reg_arch_info = calloc(num_regs, sizeof(struct arm_reg));
@@ -599,10 +667,14 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm)
        cache->reg_list = reg_list;
        cache->num_regs = 0;
 
-       for (i = 0; i < num_regs; i++) {
+       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 */
@@ -651,12 +723,62 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm)
                cache->num_regs++;
        }
 
+       int j;
+       for (i = num_core_regs, j = 0; i < num_regs; i++, j++) {
+               reg_arch_info[i].num = arm_vfp_v3_regs[j].id;
+               reg_arch_info[i].mode = arm_vfp_v3_regs[j].mode;
+               reg_arch_info[i].target = target;
+               reg_arch_info[i].arm = arm;
+
+               reg_list[i].name = arm_vfp_v3_regs[j].name;
+               reg_list[i].number = arm_vfp_v3_regs[j].id;
+               reg_list[i].size = arm_vfp_v3_regs[j].bits;
+               reg_list[i].value = reg_arch_info[i].value;
+               reg_list[i].type = &arm_reg_type;
+               reg_list[i].arch_info = &reg_arch_info[i];
+               reg_list[i].exist = true;
+
+               reg_list[i].caller_save = false;
+
+               reg_list[i].reg_data_type = malloc(sizeof(struct reg_data_type));
+               reg_list[i].reg_data_type->type = arm_vfp_v3_regs[j].type;
+
+               reg_list[i].feature = malloc(sizeof(struct reg_feature));
+               reg_list[i].feature->name = arm_vfp_v3_regs[j].feature;
+
+               reg_list[i].group = arm_vfp_v3_regs[j].group;
+
+               cache->num_regs++;
+       }
+
        arm->pc = reg_list + 15;
        arm->cpsr = reg_list + ARMV4_5_CPSR;
        arm->core_cache = cache;
+
        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);
@@ -667,7 +789,7 @@ int arm_arch_state(struct target *target)
        }
 
        /* avoid filling log waiting for fileio reply */
-       if (arm->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"
@@ -677,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),
-               arm->is_semihosting ? ", semihosting" : "",
-               arm->is_semihosting_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);
@@ -693,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");
-               return ERROR_FAIL;
+               command_print(CMD, "Error: target must be halted for register accesses");
+               return ERROR_TARGET_NOT_HALTED;
        }
 
-       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;
        }
@@ -714,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;
        }
@@ -726,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:
@@ -734,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:
@@ -743,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 */
@@ -770,358 +898,284 @@ 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);
                }
        }
 
        return ERROR_OK;
 }
 
-COMMAND_HANDLER(handle_armv4_5_core_state_command)
+COMMAND_HANDLER(handle_arm_core_state_command)
 {
        struct target *target = get_current_target(CMD_CTX);
        struct arm *arm = target_to_arm(target);
+       int ret = ERROR_OK;
 
        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) {
-               /* armv7m not supported */
-               command_print(CMD_CTX, "Unsupported Command");
-               return ERROR_OK;
-       }
-
        if (CMD_ARGC > 0) {
-               if (strcmp(CMD_ARGV[0], "arm") == 0)
-                       arm->core_state = ARM_STATE_ARM;
+               if (strcmp(CMD_ARGV[0], "arm") == 0) {
+                       if (arm->core_type == ARM_CORE_TYPE_M_PROFILE) {
+                               command_print(CMD, "arm mode not supported on Cortex-M");
+                               ret = ERROR_FAIL;
+                       } else {
+                               arm->core_state = ARM_STATE_ARM;
+                       }
+               }
                if (strcmp(CMD_ARGV[0], "thumb") == 0)
                        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;
+       return ret;
 }
 
 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)
+COMMAND_HANDLER(handle_armv4_5_mcrmrc)
 {
-       struct command_context *context;
-       struct target *target;
-       struct arm *arm;
-       int retval;
+       bool is_mcr = false;
+       unsigned int arg_cnt = 5;
+
+       if (!strcmp(CMD_NAME, "mcr")) {
+               is_mcr = true;
+               arg_cnt = 6;
+       }
 
-       context = current_command_context(interp);
-       assert(context != NULL);
+       if (arg_cnt != CMD_ARGC)
+               return ERROR_COMMAND_SYNTAX_ERROR;
 
-       target = get_current_target(context);
-       if (target == NULL) {
-               LOG_ERROR("%s: no current target", __func__);
-               return JIM_ERR;
+       struct target *target = get_current_target(CMD_CTX);
+       if (!target) {
+               command_print(CMD, "no current target");
+               return ERROR_FAIL;
        }
        if (!target_was_examined(target)) {
-               LOG_ERROR("%s: not yet examined", target_name(target));
-               return JIM_ERR;
+               command_print(CMD, "%s: not yet examined", target_name(target));
+               return ERROR_TARGET_NOT_EXAMINED;
        }
-       arm = target_to_arm(target);
+
+       struct arm *arm = target_to_arm(target);
        if (!is_arm(arm)) {
-               LOG_ERROR("%s: not an ARM", target_name(target));
-               return JIM_ERR;
+               command_print(CMD, "%s: not an ARM", target_name(target));
+               return ERROR_FAIL;
        }
 
-       if ((argc < 6) || (argc > 7)) {
-               /* FIXME use the command name to verify # params... */
-               LOG_ERROR("%s: wrong number of arguments", __func__);
-               return JIM_ERR;
+       if (target->state != TARGET_HALTED) {
+               command_print(CMD, "Error: [%s] not halted", target_name(target));
+               return ERROR_TARGET_NOT_HALTED;
        }
 
        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;
 
        /* NOTE:  parameter sequence matches ARM instruction set usage:
         *      MCR     pNUM, op1, rX, CRn, CRm, op2    ; write CP from rX
         *      MRC     pNUM, op1, rX, CRn, CRm, op2    ; read CP into rX
         * The "rX" is necessarily omitted; it uses Tcl mechanisms.
         */
-       retval = Jim_GetLong(interp, argv[1], &l);
-       if (retval != JIM_OK)
-               return retval;
-       if (l & ~0xf) {
-               LOG_ERROR("%s: %s %d out of range", __func__,
-                       "coprocessor", (int) l);
-               return JIM_ERR;
+       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], cpnum);
+       if (cpnum & ~0xf) {
+               command_print(CMD, "coprocessor %d out of range", cpnum);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
        }
-       cpnum = l;
 
-       retval = Jim_GetLong(interp, argv[2], &l);
-       if (retval != JIM_OK)
-               return retval;
-       if (l & ~0x7) {
-               LOG_ERROR("%s: %s %d out of range", __func__,
-                       "op1", (int) l);
-               return JIM_ERR;
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], op1);
+       if (op1 & ~0x7) {
+               command_print(CMD, "op1 %d out of range", op1);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
        }
-       op1 = l;
 
-       retval = Jim_GetLong(interp, argv[3], &l);
-       if (retval != JIM_OK)
-               return retval;
-       if (l & ~0xf) {
-               LOG_ERROR("%s: %s %d out of range", __func__,
-                       "CRn", (int) l);
-               return JIM_ERR;
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], crn);
+       if (crn & ~0xf) {
+               command_print(CMD, "CRn %d out of range", crn);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
        }
-       CRn = l;
 
-       retval = Jim_GetLong(interp, argv[4], &l);
-       if (retval != JIM_OK)
-               return retval;
-       if (l & ~0xf) {
-               LOG_ERROR("%s: %s %d out of range", __func__,
-                       "CRm", (int) l);
-               return JIM_ERR;
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], crm);
+       if (crm & ~0xf) {
+               command_print(CMD, "CRm %d out of range", crm);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
        }
-       CRm = l;
 
-       retval = Jim_GetLong(interp, argv[5], &l);
-       if (retval != JIM_OK)
-               return retval;
-       if (l & ~0x7) {
-               LOG_ERROR("%s: %s %d out of range", __func__,
-                       "op2", (int) l);
-               return JIM_ERR;
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], op2);
+       if (op2 & ~0x7) {
+               command_print(CMD, "op2 %d out of range", op2);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
        }
-       op2 = l;
 
-       value = 0;
-
-       /* FIXME don't assume "mrc" vs "mcr" from the number of params;
-        * that could easily be a typo!  Check both...
-        *
+       /*
         * FIXME change the call syntax here ... simplest to just pass
         * the MRC() or MCR() instruction to be executed.  That will also
         * let us support the "mrc2" and "mcr2" opcodes (toggling one bit)
         * if that's ever needed.
         */
-       if (argc == 7) {
-               retval = Jim_GetLong(interp, argv[6], &l);
-               if (retval != JIM_OK)
-                       return retval;
-               value = l;
+       if (is_mcr) {
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[5], value);
 
                /* 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) */
+               int retval = arm->mcr(target, cpnum, op1, op2, crn, crm, value);
                if (retval != ERROR_OK)
-                       return JIM_ERR;
+                       return retval;
        } else {
+               value = 0;
                /* 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) */
+               int retval = arm->mrc(target, cpnum, op1, op2, crn, crm, &value);
                if (retval != ERROR_OK)
-                       return JIM_ERR;
+                       return retval;
 
-               Jim_SetResult(interp, Jim_NewIntObj(interp, value));
+               command_print(CMD, "0x%" PRIx32, value);
        }
 
-       return JIM_OK;
+       return ERROR_OK;
 }
 
-COMMAND_HANDLER(handle_arm_semihosting_command)
+COMMAND_HANDLER(handle_armv4_5_mcrrmrrc)
 {
-       struct target *target = get_current_target(CMD_CTX);
+       bool is_mcrr = false;
+       unsigned int arg_cnt = 3;
 
-       if (target == NULL) {
-               LOG_ERROR("No target selected");
-               return ERROR_FAIL;
+       if (!strcmp(CMD_NAME, "mcrr")) {
+               is_mcrr = true;
+               arg_cnt = 4;
        }
 
-       struct arm *arm = target_to_arm(target);
-
-       if (!is_arm(arm)) {
-               command_print(CMD_CTX, "current target isn't an ARM");
-               return ERROR_FAIL;
-       }
-
-       if (!arm->setup_semihosting) {
-               command_print(CMD_CTX, "semihosting not supported for current target");
-               return ERROR_FAIL;
-       }
-
-       if (CMD_ARGC > 0) {
-               int semihosting;
-
-               COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting);
-
-               if (!target_was_examined(target)) {
-                       LOG_ERROR("Target not examined yet");
-                       return ERROR_FAIL;
-               }
-
-               if (arm->setup_semihosting(target, semihosting) != ERROR_OK) {
-                       LOG_ERROR("Failed to Configure semihosting");
-                       return ERROR_FAIL;
-               }
-
-               /* FIXME never let that "catch" be dropped! */
-               arm->is_semihosting = semihosting;
-       }
-
-       command_print(CMD_CTX, "semihosting is %s",
-               arm->is_semihosting
-               ? "enabled" : "disabled");
-
-       return ERROR_OK;
-}
+       if (arg_cnt != CMD_ARGC)
+               return ERROR_COMMAND_SYNTAX_ERROR;
 
-COMMAND_HANDLER(handle_arm_semihosting_fileio_command)
-{
        struct target *target = get_current_target(CMD_CTX);
-
-       if (target == NULL) {
-               LOG_ERROR("No target selected");
+       if (!target) {
+               command_print(CMD, "no current target");
                return ERROR_FAIL;
        }
+       if (!target_was_examined(target)) {
+               command_print(CMD, "%s: not yet examined", target_name(target));
+               return ERROR_TARGET_NOT_EXAMINED;
+       }
 
        struct arm *arm = target_to_arm(target);
-
        if (!is_arm(arm)) {
-               command_print(CMD_CTX, "current target isn't an ARM");
-               return ERROR_FAIL;
-       }
-
-       if (!arm->is_semihosting) {
-               command_print(CMD_CTX, "semihosting is not enabled");
+               command_print(CMD, "%s: not an ARM", target_name(target));
                return ERROR_FAIL;
        }
 
-       if (CMD_ARGC > 0)
-               COMMAND_PARSE_ENABLE(CMD_ARGV[0], arm->is_semihosting_fileio);
-
-       command_print(CMD_CTX, "semihosting fileio is %s",
-               arm->is_semihosting_fileio
-               ? "enabled" : "disabled");
-
-       return ERROR_OK;
-}
+       if (target->state != TARGET_HALTED)
+               return ERROR_TARGET_NOT_HALTED;
 
-COMMAND_HANDLER(handle_arm_semihosting_cmdline)
-{
-       struct target *target = get_current_target(CMD_CTX);
-       unsigned int i;
+       int cpnum;
+       uint32_t op1;
+       uint32_t crm;
+       uint64_t value;
 
-       if (target == NULL) {
-               LOG_ERROR("No target selected");
-               return ERROR_FAIL;
+       /* NOTE:  parameter sequence matches ARM instruction set usage:
+        *      MCRR    pNUM, op1, rX1, rX2, CRm        ; write CP from rX1 and rX2
+        *      MREC    pNUM, op1, rX1, rX2, CRm        ; read CP into rX1 and rX2
+        * The "rXn" are necessarily omitted; they use Tcl mechanisms.
+        */
+       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], cpnum);
+       if (cpnum & ~0xf) {
+               command_print(CMD, "coprocessor %d out of range", cpnum);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
        }
 
-       struct arm *arm = target_to_arm(target);
-
-       if (!is_arm(arm)) {
-               command_print(CMD_CTX, "current target isn't an ARM");
-               return ERROR_FAIL;
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], op1);
+       if (op1 & ~0xf) {
+               command_print(CMD, "op1 %d out of range", op1);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
        }
 
-       if (!arm->setup_semihosting) {
-               command_print(CMD_CTX, "semihosting not supported for current target");
-               return ERROR_FAIL;
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], crm);
+       if (crm & ~0xf) {
+               command_print(CMD, "CRm %d out of range", crm);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
        }
 
-       free(arm->semihosting_cmdline);
-       arm->semihosting_cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL;
+       /*
+        * FIXME change the call syntax here ... simplest to just pass
+        * the MRC() or MCR() instruction to be executed.  That will also
+        * let us support the "mrrc2" and "mcrr2" opcodes (toggling one bit)
+        * if that's ever needed.
+        */
+       if (is_mcrr) {
+               COMMAND_PARSE_NUMBER(u64, CMD_ARGV[3], value);
 
-       for (i = 1; i < CMD_ARGC; i++) {
-               char *cmdline = alloc_printf("%s %s", arm->semihosting_cmdline, CMD_ARGV[i]);
-               if (cmdline == NULL)
-                       break;
-               free(arm->semihosting_cmdline);
-               arm->semihosting_cmdline = cmdline;
+               /* NOTE: parameters reordered! */
+               /* ARMV5_T_MCRR(cpnum, op1, crm) */
+               int retval = arm->mcrr(target, cpnum, op1, crm, value);
+               if (retval != ERROR_OK)
+                       return retval;
+       } else {
+               value = 0;
+               /* NOTE: parameters reordered! */
+               /* ARMV5_T_MRRC(cpnum, op1, crm) */
+               int retval = arm->mrrc(target, cpnum, op1, crm, &value);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               command_print(CMD, "0x%" PRIx64, value);
        }
 
        return ERROR_OK;
@@ -1135,57 +1189,61 @@ static const struct command_registration arm_exec_command_handlers[] = {
                .help = "display ARM core registers",
                .usage = "",
        },
-       {
-               .name = "core_state",
-               .handler = handle_armv4_5_core_state_command,
-               .mode = COMMAND_EXEC,
-               .usage = "['arm'|'thumb']",
-               .help = "display/change ARM core state",
-       },
-       {
-               .name = "disassemble",
-               .handler = handle_arm_disassemble_command,
-               .mode = COMMAND_EXEC,
-               .usage = "address [count ['thumb']]",
-               .help = "disassemble instructions ",
-       },
        {
                .name = "mcr",
                .mode = COMMAND_EXEC,
-               .jim_handler = &jim_mcrmrc,
+               .handler = handle_armv4_5_mcrmrc,
                .help = "write coprocessor register",
                .usage = "cpnum op1 CRn CRm op2 value",
        },
        {
                .name = "mrc",
-               .jim_handler = &jim_mcrmrc,
+               .mode = COMMAND_EXEC,
+               .handler = handle_armv4_5_mcrmrc,
                .help = "read coprocessor register",
                .usage = "cpnum op1 CRn CRm op2",
        },
        {
-               "semihosting",
-               .handler = handle_arm_semihosting_command,
+               .name = "mcrr",
                .mode = COMMAND_EXEC,
-               .usage = "['enable'|'disable']",
-               .help = "activate support for semihosting operations",
+               .handler = handle_armv4_5_mcrrmrrc,
+               .help = "write coprocessor 64-bit register",
+               .usage = "cpnum op1 CRm value",
        },
        {
-               "semihosting_cmdline",
-               .handler = handle_arm_semihosting_cmdline,
+               .name = "mrrc",
                .mode = COMMAND_EXEC,
-               .usage = "arguments",
-               .help = "command line arguments to be passed to program",
+               .handler = handle_armv4_5_mcrrmrrc,
+               .help = "read coprocessor 64-bit register",
+               .usage = "cpnum op1 CRm",
        },
        {
-               "semihosting_fileio",
-               .handler = handle_arm_semihosting_fileio_command,
-               .mode = COMMAND_EXEC,
-               .usage = "['enable'|'disable']",
-               .help = "activate support for semihosting fileio operations",
+               .chain = arm_all_profiles_command_handlers,
        },
+       COMMAND_REGISTRATION_DONE
+};
 
+const struct command_registration arm_all_profiles_command_handlers[] = {
+       {
+               .name = "core_state",
+               .handler = handle_arm_core_state_command,
+               .mode = COMMAND_EXEC,
+               .usage = "['arm'|'thumb']",
+               .help = "display/change ARM core state",
+       },
+       {
+               .name = "disassemble",
+               .handler = handle_arm_disassemble_command,
+               .mode = COMMAND_EXEC,
+               .usage = "address [count ['thumb']]",
+               .help = "disassemble instructions",
+       },
+       {
+               .chain = semihosting_common_handlers,
+       },
        COMMAND_REGISTRATION_DONE
 };
+
 const struct command_registration arm_command_handlers[] = {
        {
                .name = "arm",
@@ -1197,6 +1255,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(const 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)
@@ -1225,10 +1297,22 @@ 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;
+
                *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
 
                for (i = 0; i < 16; i++)
@@ -1236,9 +1320,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 */
@@ -1249,20 +1339,24 @@ int arm_get_gdb_reg_list(struct target *target,
                (*reg_list)[24] = &arm_gdb_dummy_fps_reg;
                (*reg_list)[24]->size = 0;
 
+               if (arm->arm_vfp_version == ARM_VFP_V3) {
+                       unsigned int num_core_regs = ARRAY_SIZE(arm_core_regs);
+                       for (i = 0; i < 33; i++)
+                               (*reg_list)[list_size_core + i] = &(arm->core_cache->reg_list[num_core_regs + i]);
+               }
+
                return ERROR_OK;
-               break;
 
        default:
                LOG_ERROR("not a valid register class type in query.");
                return ERROR_FAIL;
-               break;
        }
 }
 
 /* wait for execution to complete and check exit point */
 static int armv4_5_run_algorithm_completion(struct target *target,
        uint32_t exit_point,
-       int timeout_ms,
+       unsigned int timeout_ms,
        void *arch_info)
 {
        int retval;
@@ -1296,9 +1390,9 @@ int armv4_5_run_algorithm_inner(struct target *target,
        int num_mem_params, struct mem_param *mem_params,
        int num_reg_params, struct reg_param *reg_params,
        uint32_t entry_point, uint32_t exit_point,
-       int timeout_ms, void *arch_info,
+       unsigned int timeout_ms, void *arch_info,
        int (*run_it)(struct target *target, uint32_t exit_point,
-       int timeout_ms, void *arch_info))
+       unsigned int timeout_ms, void *arch_info))
 {
        struct arm *arm = target_to_arm(target);
        struct arm_algorithm *arm_algorithm_info = arch_info;
@@ -1317,7 +1411,7 @@ int armv4_5_run_algorithm_inner(struct target *target,
        }
 
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target not halted");
+               LOG_TARGET_ERROR(target, "not halted (run target algo)");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -1327,7 +1421,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;
        }
@@ -1348,6 +1442,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)
@@ -1355,7 +1451,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;
@@ -1387,8 +1486,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 */
@@ -1427,7 +1526,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;
@@ -1458,14 +1557,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;
 
@@ -1479,7 +1578,7 @@ int armv4_5_run_algorithm(struct target *target,
        struct reg_param *reg_params,
        target_addr_t entry_point,
        target_addr_t exit_point,
-       int timeout_ms,
+       unsigned int timeout_ms,
        void *arch_info)
 {
        return armv4_5_run_algorithm_inner(target,
@@ -1540,10 +1639,10 @@ int arm_checksum_memory(struct target *target,
        buf_set_u32(reg_params[1].value, 0, 32, count);
 
        /* 20 second timeout/megabyte */
-       int timeout = 20000 * (1 + (count / (1024 * 1024)));
+       unsigned 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,
@@ -1572,7 +1671,7 @@ cleanup:
  *
  */
 int arm_blank_check_memory(struct target *target,
-       target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
+       struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value)
 {
        struct working_area *check_algorithm;
        struct reg_param reg_params[3];
@@ -1615,16 +1714,16 @@ int arm_blank_check_memory(struct target *target,
        arm_algo.core_state = ARM_STATE_ARM;
 
        init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
-       buf_set_u32(reg_params[0].value, 0, 32, address);
+       buf_set_u32(reg_params[0].value, 0, 32, blocks[0].address);
 
        init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
-       buf_set_u32(reg_params[1].value, 0, 32, count);
+       buf_set_u32(reg_params[1].value, 0, 32, blocks[0].size);
 
        init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
        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,
@@ -1633,7 +1732,7 @@ int arm_blank_check_memory(struct target *target,
                        10000, &arm_algo);
 
        if (retval == ERROR_OK)
-               *blank = buf_get_u32(reg_params[2].value, 0, 32);
+               blocks[0].result = buf_get_u32(reg_params[2].value, 0, 32);
 
        destroy_reg_param(&reg_params[0]);
        destroy_reg_param(&reg_params[1]);
@@ -1642,7 +1741,10 @@ int arm_blank_check_memory(struct target *target,
 cleanup:
        target_free_working_area(target, check_algorithm);
 
-       return retval;
+       if (retval != ERROR_OK)
+               return retval;
+
+       return 1;       /* only one block has been checked */
 }
 
 static int arm_full_context(struct target *target)
@@ -1653,7 +1755,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);
        }
@@ -1662,22 +1764,38 @@ 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));
        return ERROR_FAIL;
 }
 
+static int arm_default_mrrc(struct target *target, int cpnum,
+       uint32_t op, uint32_t crm,
+       uint64_t *value)
+{
+       LOG_ERROR("%s doesn't implement MRRC", target_type_name(target));
+       return ERROR_FAIL;
+}
+
 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));
        return ERROR_FAIL;
 }
 
+static int arm_default_mcrr(struct target *target, int cpnum,
+       uint32_t op, uint32_t crm,
+       uint64_t value)
+{
+       LOG_ERROR("%s doesn't implement MCRR", target_type_name(target));
+       return ERROR_FAIL;
+}
+
 int arm_init_arch_info(struct target *target, struct arm *arm)
 {
        target->arch_info = arm;
@@ -1686,8 +1804,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);
        }
 
@@ -1697,8 +1815,12 @@ int arm_init_arch_info(struct target *target, struct arm *arm)
 
        if (!arm->mrc)
                arm->mrc = arm_default_mrc;
+       if (!arm->mrrc)
+               arm->mrrc = arm_default_mrrc;
        if (!arm->mcr)
                arm->mcr = arm_default_mcr;
+       if (!arm->mcrr)
+               arm->mcrr = arm_default_mcrr;
 
        return ERROR_OK;
 }

Linking to existing account procedure

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

SSH host keys fingerprints

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