X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Ftarget%2Farmv8.c;h=1981e7c3d5765a39ee2140dfdda593400964c782;hb=c0ec54d8ae8f7f933718f9d05efdde986b51f98c;hp=e8c700af35d8da9ca166a34f77f5597ae5fffd02;hpb=ffd6b78a2c47d1c15629dc72c71caea30ef8161a;p=fw%2Fopenocd diff --git a/src/target/armv8.c b/src/target/armv8.c index e8c700af3..1981e7c3d 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1,6 +1,9 @@ /*************************************************************************** * Copyright (C) 2015 by David Ung * * * + * Copyright (C) 2018 by Liviu Ionescu * + * * + * * * 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 * @@ -36,6 +39,7 @@ #include "armv8_opcodes.h" #include "target.h" #include "target_type.h" +#include "semihosting_common.h" static const char * const armv8_state_strings[] = { "AArch32", "Thumb", "Jazelle", "ThumbEE", "AArch64", @@ -932,6 +936,11 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, "Secure", "Not Secure" }; + if (target->state != TARGET_HALTED) { + LOG_WARNING("target %s not halted", target_name(target)); + return ERROR_TARGET_NOT_HALTED; + } + retval = dpm->prepare(dpm); if (retval != ERROR_OK) return retval; @@ -1013,11 +1022,24 @@ int armv8_handle_cache_info_command(struct command_context *cmd_ctx, return ERROR_OK; } +static int armv8_setup_semihosting(struct target *target, int enable) +{ + struct arm *arm = target_to_arm(target); + + if (arm->core_state != ARM_STATE_AARCH64) { + LOG_ERROR("semihosting only supported in AArch64 state\n"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + int armv8_init_arch_info(struct target *target, struct armv8_common *armv8) { struct arm *arm = &armv8->arm; arm->arch_info = armv8; target->arch_info = &armv8->arm; + arm->setup_semihosting = armv8_setup_semihosting; /* target is useful in all function arm v4 5 compatible */ armv8->arm.target = target; armv8->arm.common_magic = ARM_COMMON_MAGIC; @@ -1046,7 +1068,7 @@ int armv8_aarch64_state(struct target *target) armv8_mode_name(arm->core_mode), buf_get_u32(arm->cpsr->value, 0, 32), buf_get_u64(arm->pc->value, 0, 64), - arm->is_semihosting ? ", semihosting" : ""); + (target->semihosting && target->semihosting->is_active) ? ", semihosting" : ""); return ERROR_OK; } @@ -1186,7 +1208,49 @@ static struct reg_data_type_union aarch64v_union[] = { }; static struct reg_data_type aarch64v[] = { - {REG_TYPE_ARCH_DEFINED, "aarch64v", REG_TYPE_CLASS_UNION, {.reg_type_union = aarch64v_union} }, + {REG_TYPE_ARCH_DEFINED, "aarch64v", REG_TYPE_CLASS_UNION, + {.reg_type_union = aarch64v_union} }, +}; + +static struct reg_data_type_bitfield aarch64_cpsr_bits[] = { + { 0, 0 , REG_TYPE_UINT8 }, + { 2, 3, REG_TYPE_UINT8 }, + { 4, 4 , REG_TYPE_UINT8 }, + { 6, 6 , REG_TYPE_BOOL }, + { 7, 7 , REG_TYPE_BOOL }, + { 8, 8 , REG_TYPE_BOOL }, + { 9, 9 , REG_TYPE_BOOL }, + { 20, 20, REG_TYPE_BOOL }, + { 21, 21, REG_TYPE_BOOL }, + { 28, 28, REG_TYPE_BOOL }, + { 29, 29, REG_TYPE_BOOL }, + { 30, 30, REG_TYPE_BOOL }, + { 31, 31, REG_TYPE_BOOL }, +}; + +static struct reg_data_type_flags_field aarch64_cpsr_fields[] = { + { "SP", aarch64_cpsr_bits + 0, aarch64_cpsr_fields + 1 }, + { "EL", aarch64_cpsr_bits + 1, aarch64_cpsr_fields + 2 }, + { "nRW", aarch64_cpsr_bits + 2, aarch64_cpsr_fields + 3 }, + { "F" , aarch64_cpsr_bits + 3, aarch64_cpsr_fields + 4 }, + { "I" , aarch64_cpsr_bits + 4, aarch64_cpsr_fields + 5 }, + { "A" , aarch64_cpsr_bits + 5, aarch64_cpsr_fields + 6 }, + { "D" , aarch64_cpsr_bits + 6, aarch64_cpsr_fields + 7 }, + { "IL" , aarch64_cpsr_bits + 7, aarch64_cpsr_fields + 8 }, + { "SS" , aarch64_cpsr_bits + 8, aarch64_cpsr_fields + 9 }, + { "V" , aarch64_cpsr_bits + 9, aarch64_cpsr_fields + 10 }, + { "C" , aarch64_cpsr_bits + 10, aarch64_cpsr_fields + 11 }, + { "Z" , aarch64_cpsr_bits + 11, aarch64_cpsr_fields + 12 }, + { "N" , aarch64_cpsr_bits + 12, NULL } +}; + +static struct reg_data_type_flags aarch64_cpsr_flags[] = { + { 4, aarch64_cpsr_fields } +}; + +static struct reg_data_type aarch64_flags_cpsr[] = { + {REG_TYPE_ARCH_DEFINED, "cpsr_flags", REG_TYPE_CLASS_FLAGS, + {.reg_type_flags = aarch64_cpsr_flags} }, }; static const struct { @@ -1233,9 +1297,8 @@ static const struct { { ARMV8_SP, "sp", 64, ARM_MODE_ANY, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.aarch64.core", NULL}, { ARMV8_PC, "pc", 64, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.aarch64.core", NULL}, - - { ARMV8_xPSR, "CPSR", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.aarch64.core", NULL}, - + { ARMV8_xPSR, "cpsr", 32, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, + "general", "org.gnu.gdb.aarch64.core", aarch64_flags_cpsr}, { ARMV8_V0, "v0", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v}, { ARMV8_V1, "v1", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v}, { ARMV8_V2, "v2", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v}, @@ -1414,6 +1477,9 @@ static int armv8_get_core_reg32(struct reg *reg) struct reg *reg64; int retval; + if (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + /* get the corresponding Aarch64 register */ reg64 = cache->reg_list + armv8_reg->num; if (reg64->valid) { @@ -1437,6 +1503,9 @@ static int armv8_set_core_reg32(struct reg *reg, uint8_t *buf) struct reg *reg64 = cache->reg_list + armv8_reg->num; uint32_t value = buf_get_u32(buf, 0, 32); + if (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + if (reg64 == arm->cpsr) { armv8_set_cpsr(arm, value); } else { @@ -1506,15 +1575,14 @@ struct reg_cache *armv8_build_reg_cache(struct target *target) } else LOG_ERROR("unable to allocate feature list"); - if (armv8_regs[i].data_type == NULL) { - reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type)); - if (reg_list[i].reg_data_type) + reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type)); + if (reg_list[i].reg_data_type) { + if (armv8_regs[i].data_type == NULL) reg_list[i].reg_data_type->type = armv8_regs[i].type; else - LOG_ERROR("unable to allocate reg type list"); + *reg_list[i].reg_data_type = *armv8_regs[i].data_type; } else - reg_list[i].reg_data_type = armv8_regs[i].data_type; - + LOG_ERROR("unable to allocate reg type list"); } arm->cpsr = reg_list + ARMV8_xPSR; @@ -1567,13 +1635,49 @@ struct reg *armv8_reg_current(struct arm *arm, unsigned regnum) return r; } +static void armv8_free_cache(struct reg_cache *cache, bool regs32) +{ + struct reg *reg; + unsigned int i; + + if (!cache) + return; + + for (i = 0; i < cache->num_regs; i++) { + reg = &cache->reg_list[i]; + + free(reg->feature); + free(reg->reg_data_type); + } + + if (!regs32) + free(cache->reg_list[0].arch_info); + free(cache->reg_list); + free(cache); +} + +void armv8_free_reg_cache(struct target *target) +{ + struct armv8_common *armv8 = target_to_armv8(target); + struct arm *arm = &armv8->arm; + struct reg_cache *cache = NULL, *cache32 = NULL; + + cache = arm->core_cache; + if (cache != NULL) + cache32 = cache->next; + armv8_free_cache(cache32, true); + armv8_free_cache(cache, false); + arm->core_cache = NULL; +} + const struct command_registration armv8_command_handlers[] = { - { - .chain = dap_command_handlers, - }, COMMAND_REGISTRATION_DONE }; +const char *armv8_get_gdb_arch(struct target *target) +{ + return "aarch64"; +} int armv8_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size,