x86_32_common: fix some warnings
[openocd.git] / src / target / armv8.c
index b55c153f5a6f92366e1e3d78d6a5ba1593ac8e42..1b8e450164c0fac0b027cd451b35fac505900d38 100644 (file)
@@ -37,8 +37,6 @@
 #include "target.h"
 #include "target_type.h"
 
-#define __unused __attribute__((unused))
-
 static const char * const armv8_state_strings[] = {
        "AArch32", "Thumb", "Jazelle", "ThumbEE", "AArch64",
 };
@@ -46,14 +44,7 @@ static const char * const armv8_state_strings[] = {
 static const struct {
        const char *name;
        unsigned psr;
-       /* For user and system modes, these list indices for all registers.
-        * otherwise they're just indices for the shadow registers and SPSR.
-        */
-       unsigned short n_indices;
-       const uint8_t *indices;
 } armv8_mode_data[] = {
-       /* These special modes are currently only supported
-        * by ARMv6M and ARMv7M profiles */
        {
                .name = "USR",
                .psr = ARM_MODE_USR,
@@ -119,48 +110,6 @@ const char *armv8_mode_name(unsigned psr_mode)
        return "UNRECOGNIZED";
 }
 
-int armv8_mode_to_number(enum arm_mode mode)
-{
-       switch (mode) {
-               case ARM_MODE_ANY:
-               /* map MODE_ANY to user mode */
-               case ARM_MODE_USR:
-                       return 0;
-               case ARM_MODE_FIQ:
-                       return 1;
-               case ARM_MODE_IRQ:
-                       return 2;
-               case ARM_MODE_SVC:
-                       return 3;
-               case ARM_MODE_ABT:
-                       return 4;
-               case ARM_MODE_UND:
-                       return 5;
-               case ARM_MODE_SYS:
-                       return 6;
-               case ARM_MODE_MON:
-                       return 7;
-               case ARMV8_64_EL0T:
-                       return 8;
-               case ARMV8_64_EL1T:
-                       return 9;
-               case ARMV8_64_EL1H:
-                       return 10;
-               case ARMV8_64_EL2T:
-                       return 11;
-               case ARMV8_64_EL2H:
-                       return 12;
-               case ARMV8_64_EL3T:
-                       return 13;
-               case ARMV8_64_EL3H:
-                       return 14;
-
-               default:
-                       LOG_ERROR("invalid mode value encountered %d", mode);
-                       return -1;
-       }
-}
-
 static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regval)
 {
        struct arm_dpm *dpm = &armv8->dpm;
@@ -413,8 +362,7 @@ static int armv8_write_reg32(struct armv8_common *armv8, int regnum, uint64_t va
                break;
        case ARMV8_SP:
                retval = dpm->instr_write_data_dcc(dpm,
-                       ARMV4_5_MRC(14, 0, 13, 0, 5, 0),
-                       value);
+                               ARMV4_5_MRC(14, 0, 13, 0, 5, 0), value);
                        break;
        case ARMV8_PC:/* PC
                 * read r0 from DCC; then "MOV pc, r0" */
@@ -510,10 +458,9 @@ int armv8_read_mpidr(struct armv8_common *armv8)
                LOG_INFO("%s cluster %x core %x %s", target_name(armv8->arm.target),
                        armv8->cluster_id,
                        armv8->cpu_id,
-                       armv8->multi_processor_system == 0 ? "multi core" : "mono core");
-
+                       armv8->multi_processor_system == 0 ? "multi core" : "single core");
        } else
-               LOG_ERROR("mpdir not in multiprocessor format");
+               LOG_ERROR("mpidr not in multiprocessor format");
 
 done:
        dpm->finish(dpm);
@@ -542,9 +489,8 @@ void armv8_set_cpsr(struct arm *arm, uint32_t cpsr)
        /* Older ARMs won't have the J bit */
        enum arm_state state = 0xFF;
 
-       if (((cpsr & 0x10) >> 4) == 0) {
-               state = ARM_STATE_AARCH64;
-       } else {
+       if ((cpsr & 0x10) != 0) {
+               /* Aarch32 state */
                if (cpsr & (1 << 5)) {  /* T */
                        if (cpsr & (1 << 24)) { /* J */
                                LOG_WARNING("ThumbEE -- incomplete support");
@@ -558,12 +504,13 @@ void armv8_set_cpsr(struct arm *arm, uint32_t cpsr)
                        } else
                                state = ARM_STATE_ARM;
                }
+       } else {
+               /* Aarch64 state */
+               state = ARM_STATE_AARCH64;
        }
+
        arm->core_state = state;
-       if (arm->core_state == ARM_STATE_AARCH64)
-               arm->core_mode = (mode << 4) | 0xf;
-       else
-               arm->core_mode = mode;
+       arm->core_mode = mode;
 
        LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr,
                armv8_mode_name(arm->core_mode),
@@ -617,7 +564,7 @@ done:
        /* (void) */ dpm->finish(dpm);
 }
 
-static void armv8_show_fault_registers(struct target *target)
+static __attribute__((unused)) void armv8_show_fault_registers(struct target *target)
 {
        struct armv8_common *armv8 = target_to_armv8(target);
 
@@ -654,7 +601,7 @@ static uint8_t armv8_pa_size(uint32_t ps)
        return ret;
 }
 
-static __unused int armv8_read_ttbcr32(struct target *target)
+static __attribute__((unused)) int armv8_read_ttbcr32(struct target *target)
 {
        struct armv8_common *armv8 = target_to_armv8(target);
        struct arm_dpm *dpm = armv8->arm.dpm;
@@ -693,7 +640,7 @@ done:
        return retval;
 }
 
-static __unused int armv8_read_ttbcr(struct target *target)
+static __attribute__((unused)) int armv8_read_ttbcr(struct target *target)
 {
        struct armv8_common *armv8 = target_to_armv8(target);
        struct arm_dpm *dpm = armv8->arm.dpm;
@@ -737,6 +684,8 @@ static __unused int armv8_read_ttbcr(struct target *target)
                armv8->page_size = (ttbcr >> 14) & 3;
                break;
        case SYSTEM_CUREL_EL0:
+               armv8_dpm_modeswitch(dpm, ARMV8_64_EL1H);
+               /* fall through */
        case SYSTEM_CUREL_EL1:
                retval = dpm->instr_read_data_r0_64(dpm,
                                ARMV8_MRS(SYSTEM_TCR_EL1, 0),
@@ -764,6 +713,7 @@ static __unused int armv8_read_ttbcr(struct target *target)
                LOG_INFO("TTBR0 access above %" PRIx64, (uint64_t)(armv8->armv8_mmu.ttbr0_mask));
 
 done:
+       armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
        dpm->finish(dpm);
        return retval;
 }
@@ -835,9 +785,6 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va,
 
        dpm->finish(dpm);
 
-       if (retval != ERROR_OK)
-               return retval;
-
        if (retval != ERROR_OK)
                return retval;
 
@@ -1009,12 +956,39 @@ static const struct {
        { ARMV8_SPSR_EL3, "SPSR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" },
 };
 
-#define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
+static const struct {
+       unsigned id;
+       const char *name;
+       unsigned bits;
+       enum arm_mode mode;
+       enum reg_type type;
+       const char *group;
+       const char *feature;
+} armv8_regs32[] = {
+       { ARMV8_R0,  "r0",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R1,  "r1",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R2,  "r2",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R3,  "r3",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R4,  "r4",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R5,  "r5",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R6,  "r6",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R7,  "r7",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R8,  "r8",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R9,  "r9",  32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R10, "r10", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R11, "r11", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R12, "r12", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R13, "sp", 32, ARM_MODE_ANY, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_R14, "lr",  32, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_PC, "pc",   32, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.core" },
+       { ARMV8_xPSR, "cpsr", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+};
 
+#define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
+#define ARMV8_NUM_REGS32 ARRAY_SIZE(armv8_regs32)
 
 static int armv8_get_core_reg(struct reg *reg)
 {
-       int retval;
        struct arm_reg *armv8_reg = reg->arch_info;
        struct target *target = armv8_reg->target;
        struct arm *arm = target_to_arm(target);
@@ -1022,9 +996,7 @@ static int armv8_get_core_reg(struct reg *reg)
        if (target->state != TARGET_HALTED)
                return ERROR_TARGET_NOT_HALTED;
 
-       retval = arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode);
-
-       return retval;
+       return arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode);
 }
 
 static int armv8_set_core_reg(struct reg *reg, uint8_t *buf)
@@ -1054,25 +1026,77 @@ static const struct reg_arch_type armv8_reg_type = {
        .set = armv8_set_core_reg,
 };
 
+static int armv8_get_core_reg32(struct reg *reg)
+{
+       struct arm_reg *armv8_reg = reg->arch_info;
+       struct target *target = armv8_reg->target;
+       struct arm *arm = target_to_arm(target);
+       struct reg_cache *cache = arm->core_cache;
+       struct reg *reg64;
+       int retval;
+
+       /* get the corresponding Aarch64 register */
+       reg64 = cache->reg_list + armv8_reg->num;
+       if (reg64->valid) {
+               reg->valid = true;
+               return ERROR_OK;
+       }
+
+       retval = arm->read_core_reg(target, reg64, armv8_reg->num, arm->core_mode);
+       if (retval == ERROR_OK)
+               reg->valid = reg64->valid;
+
+       return retval;
+}
+
+static int armv8_set_core_reg32(struct reg *reg, uint8_t *buf)
+{
+       struct arm_reg *armv8_reg = reg->arch_info;
+       struct target *target = armv8_reg->target;
+       struct arm *arm = target_to_arm(target);
+       struct reg_cache *cache = arm->core_cache;
+       struct reg *reg64 = cache->reg_list + armv8_reg->num;
+       uint32_t value = buf_get_u32(buf, 0, 32);
+
+       if (reg64 == arm->cpsr) {
+               armv8_set_cpsr(arm, value);
+       } else {
+               buf_set_u32(reg->value, 0, 32, value);
+               reg->valid = 1;
+               reg64->valid = 1;
+       }
+
+       reg64->dirty = 1;
+
+       return ERROR_OK;
+}
+
+static const struct reg_arch_type armv8_reg32_type = {
+       .get = armv8_get_core_reg32,
+       .set = armv8_set_core_reg32,
+};
+
 /** Builds cache of architecturally defined registers.  */
 struct reg_cache *armv8_build_reg_cache(struct target *target)
 {
        struct armv8_common *armv8 = target_to_armv8(target);
        struct arm *arm = &armv8->arm;
        int num_regs = ARMV8_NUM_REGS;
+       int num_regs32 = ARMV8_NUM_REGS32;
        struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
        struct reg_cache *cache = malloc(sizeof(struct reg_cache));
+       struct reg_cache *cache32 = malloc(sizeof(struct reg_cache));
        struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
+       struct reg *reg_list32 = calloc(num_regs32, sizeof(struct reg));
        struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
        struct reg_feature *feature;
        int i;
 
        /* Build the process context cache */
-       cache->name = "arm v8 registers";
-       cache->next = NULL;
+       cache->name = "Aarch64 registers";
+       cache->next = cache32;
        cache->reg_list = reg_list;
        cache->num_regs = num_regs;
-       (*cache_p) = cache;
 
        for (i = 0; i < num_regs; i++) {
                arch_info[i].num = armv8_regs[i].id;
@@ -1082,9 +1106,7 @@ struct reg_cache *armv8_build_reg_cache(struct target *target)
 
                reg_list[i].name = armv8_regs[i].name;
                reg_list[i].size = armv8_regs[i].bits;
-               reg_list[i].value = calloc(1, 8);
-               reg_list[i].dirty = 0;
-               reg_list[i].valid = 0;
+               reg_list[i].value = &arch_info[i].value[0];
                reg_list[i].type = &armv8_reg_type;
                reg_list[i].arch_info = &arch_info[i];
 
@@ -1111,6 +1133,38 @@ struct reg_cache *armv8_build_reg_cache(struct target *target)
        arm->pc = reg_list + ARMV8_PC;
        arm->core_cache = cache;
 
+       /* shadow cache for ARM mode registers */
+       cache32->name = "Aarch32 registers";
+       cache32->next = NULL;
+       cache32->reg_list = reg_list32;
+       cache32->num_regs = num_regs32;
+
+       for (i = 0; i < num_regs32; i++) {
+               reg_list32[i].name = armv8_regs32[i].name;
+               reg_list32[i].size = armv8_regs32[i].bits;
+               reg_list32[i].value = &arch_info[armv8_regs32[i].id].value[0];
+               reg_list32[i].type = &armv8_reg32_type;
+               reg_list32[i].arch_info = &arch_info[armv8_regs32[i].id];
+               reg_list32[i].group = armv8_regs32[i].group;
+               reg_list32[i].number = i;
+               reg_list32[i].exist = true;
+               reg_list32[i].caller_save = true;
+
+               feature = calloc(1, sizeof(struct reg_feature));
+               if (feature) {
+                       feature->name = armv8_regs32[i].feature;
+                       reg_list32[i].feature = feature;
+               } else
+                       LOG_ERROR("unable to allocate feature list");
+
+               reg_list32[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
+               if (reg_list32[i].reg_data_type)
+                       reg_list32[i].reg_data_type->type = armv8_regs32[i].type;
+               else
+                       LOG_ERROR("unable to allocate reg type list");
+       }
+
+       (*cache_p) = cache;
        return cache;
 }
 
@@ -1140,27 +1194,71 @@ int armv8_get_gdb_reg_list(struct target *target,
        struct arm *arm = target_to_arm(target);
        int i;
 
-       switch (reg_class) {
-       case REG_CLASS_GENERAL:
-               *reg_list_size = ARMV8_ELR_EL1;
-               *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
+       if (arm->core_state == ARM_STATE_AARCH64) {
 
-               for (i = 0; i < *reg_list_size; i++)
-                               (*reg_list)[i] = armv8_reg_current(arm, i);
+               LOG_DEBUG("Creating Aarch64 register list for target %s", target_name(target));
 
-               return ERROR_OK;
-       case REG_CLASS_ALL:
-               *reg_list_size = ARMV8_LAST_REG;
-               *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
+               switch (reg_class) {
+               case REG_CLASS_GENERAL:
+                       *reg_list_size = ARMV8_ELR_EL1;
+                       *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
 
-               for (i = 0; i < *reg_list_size; i++)
-                               (*reg_list)[i] = armv8_reg_current(arm, i);
+                       for (i = 0; i < *reg_list_size; i++)
+                                       (*reg_list)[i] = armv8_reg_current(arm, i);
+                       return ERROR_OK;
 
-               return ERROR_OK;
+               case REG_CLASS_ALL:
+                       *reg_list_size = ARMV8_LAST_REG;
+                       *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
 
-       default:
-               LOG_ERROR("not a valid register class type in query.");
-               return ERROR_FAIL;
-               break;
+                       for (i = 0; i < *reg_list_size; i++)
+                                       (*reg_list)[i] = armv8_reg_current(arm, i);
+
+                       return ERROR_OK;
+
+               default:
+                       LOG_ERROR("not a valid register class type in query.");
+                       return ERROR_FAIL;
+               }
+       } else {
+               struct reg_cache *cache32 = arm->core_cache->next;
+
+               LOG_DEBUG("Creating Aarch32 register list for target %s", target_name(target));
+
+               switch (reg_class) {
+               case REG_CLASS_GENERAL:
+               case REG_CLASS_ALL:
+                       *reg_list_size = cache32->num_regs;
+                       *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
+
+                       for (i = 0; i < *reg_list_size; i++)
+                               (*reg_list)[i] = cache32->reg_list + i;
+
+                       return ERROR_OK;
+               default:
+                       LOG_ERROR("not a valid register class type in query.");
+                       return ERROR_FAIL;
+               }
        }
 }
+
+int armv8_set_dbgreg_bits(struct armv8_common *armv8, unsigned int reg, unsigned long mask, unsigned long value)
+{
+       uint32_t tmp;
+
+       /* Read register */
+       int retval = mem_ap_read_atomic_u32(armv8->debug_ap,
+                       armv8->debug_base + reg, &tmp);
+       if (ERROR_OK != retval)
+               return retval;
+
+       /* clear bitfield */
+       tmp &= ~mask;
+       /* put new value */
+       tmp |= value & mask;
+
+       /* write new value */
+       retval = mem_ap_write_atomic_u32(armv8->debug_ap,
+                       armv8->debug_base + reg, tmp);
+       return retval;
+}

Linking to existing account procedure

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

SSH host keys fingerprints

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