]> git.sur5r.net Git - openocd/blobdiff - src/target/armv4_5.c
ARM: only use one set of dummy FPA registers
[openocd] / src / target / armv4_5.c
index 7c4861ffff7cb83724e069d16e25161cb5111e26..aba44319694955caf41fed9b7e7e649066ee99b3 100644 (file)
@@ -116,8 +116,6 @@ char* armv4_5_state_strings[] =
        "ARM", "Thumb", "Jazelle"
 };
 
-int armv4_5_core_reg_arch_type = -1;
-
 struct armv4_5_core_reg armv4_5_core_reg_list_arch_info[] =
 {
        {0, ARMV4_5_MODE_ANY, NULL, NULL},
@@ -191,32 +189,44 @@ int armv4_5_core_reg_map[7][17] =
        }
 };
 
-uint8_t armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const uint8_t arm_gdb_dummy_fp_value[12];
 
-struct reg armv4_5_gdb_dummy_fp_reg =
+/**
+ * Dummy FPA registers are required to support GDB on ARM.
+ * Register packets require eight obsolete FPA register values.
+ * 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 =
 {
-       .name = "GDB dummy floating-point register",
-       .value = armv4_5_gdb_dummy_fp_value,
-       .dirty = 0,
+       .name = "GDB dummy FPA register",
+       .value = (uint8_t *) arm_gdb_dummy_fp_value,
        .valid = 1,
        .size = 96,
-       .arch_info = NULL,
-       .arch_type = 0,
 };
 
-uint8_t armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0};
+static const uint8_t arm_gdb_dummy_fps_value[4];
 
-struct reg armv4_5_gdb_dummy_fps_reg =
+/**
+ * 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 =
 {
-       .name = "GDB dummy floating-point status register",
-       .value = armv4_5_gdb_dummy_fps_value,
-       .dirty = 0,
+       .name = "GDB dummy FPA status register",
+       .value = (uint8_t *) arm_gdb_dummy_fps_value,
        .valid = 1,
        .size = 32,
-       .arch_info = NULL,
-       .arch_type = 0,
 };
 
+static void arm_gdb_dummy_init(void) __attribute__ ((constructor));
+
+static void arm_gdb_dummy_init(void)
+{
+       register_init_dummy(&arm_gdb_dummy_fp_reg);
+       register_init_dummy(&arm_gdb_dummy_fps_reg);
+}
+
 int armv4_5_get_core_reg(struct reg *reg)
 {
        int retval;
@@ -285,6 +295,11 @@ int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
        return ERROR_OK;
 }
 
+static const struct reg_arch_type arm_reg_type = {
+       .get = armv4_5_get_core_reg,
+       .set = armv4_5_set_core_reg,
+};
+
 int armv4_5_invalidate_core_regs(struct target *target)
 {
        struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
@@ -312,12 +327,6 @@ struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *arm
        cache->reg_list = reg_list;
        cache->num_regs = num_regs;
 
-       if (armv4_5_core_reg_arch_type == -1)
-               armv4_5_core_reg_arch_type = register_reg_arch_type(armv4_5_get_core_reg, armv4_5_set_core_reg);
-
-       register_init_dummy(&armv4_5_gdb_dummy_fp_reg);
-       register_init_dummy(&armv4_5_gdb_dummy_fps_reg);
-
        for (i = 0; i < 37; i++)
        {
                arch_info[i] = armv4_5_core_reg_list_arch_info[i];
@@ -328,7 +337,7 @@ struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *arm
                reg_list[i].value = calloc(1, 4);
                reg_list[i].dirty = 0;
                reg_list[i].valid = 0;
-               reg_list[i].arch_type = armv4_5_core_reg_arch_type;
+               reg_list[i].type = &arm_reg_type;
                reg_list[i].arch_info = &arch_info[i];
        }
 
@@ -342,7 +351,7 @@ int armv4_5_arch_state(struct target *target)
        if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
        {
                LOG_ERROR("BUG: called for a non-ARMv4/5 target");
-               exit(-1);
+               return ERROR_FAIL;
        }
 
        LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "",
@@ -360,24 +369,30 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
        char output[128];
        int output_len;
        int mode, num;
-       struct target *target = get_current_target(cmd_ctx);
+       struct target *target = get_current_target(CMD_CTX);
        struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
 
        if (!is_arm(armv4_5))
        {
-               command_print(cmd_ctx, "current target isn't an ARM");
+               command_print(CMD_CTX, "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_CTX, "error: target must be halted for register accesses");
                return ERROR_OK;
        }
 
        if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
                return ERROR_FAIL;
 
+       if (!armv4_5->full_context) {
+               command_print(CMD_CTX, "error: target doesn't support %s",
+                               CMD_NAME);
+               return ERROR_FAIL;
+       }
+
        for (num = 0; num <= 15; num++)
        {
                output_len = 0;
@@ -393,9 +408,9 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
                                               ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name,
                                               buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32));
                }
-               command_print(cmd_ctx, "%s", output);
+               command_print(CMD_CTX, "%s", output);
        }
-       command_print(cmd_ctx,
+       command_print(CMD_CTX,
                      "    cpsr: %8.8" PRIx32 " spsr_fiq: %8.8" PRIx32 " spsr_irq: %8.8" PRIx32 " spsr_svc: %8.8" PRIx32 " spsr_abt: %8.8" PRIx32 " spsr_und: %8.8" PRIx32 "",
                          buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
                          buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32),
@@ -409,28 +424,28 @@ COMMAND_HANDLER(handle_armv4_5_reg_command)
 
 COMMAND_HANDLER(handle_armv4_5_core_state_command)
 {
-       struct target *target = get_current_target(cmd_ctx);
+       struct target *target = get_current_target(CMD_CTX);
        struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
 
        if (!is_arm(armv4_5))
        {
-               command_print(cmd_ctx, "current target isn't an ARM");
+               command_print(CMD_CTX, "current target isn't an ARM");
                return ERROR_FAIL;
        }
 
-       if (argc > 0)
+       if (CMD_ARGC > 0)
        {
-               if (strcmp(args[0], "arm") == 0)
+               if (strcmp(CMD_ARGV[0], "arm") == 0)
                {
                        armv4_5->core_state = ARMV4_5_STATE_ARM;
                }
-               if (strcmp(args[0], "thumb") == 0)
+               if (strcmp(CMD_ARGV[0], "thumb") == 0)
                {
                        armv4_5->core_state = ARMV4_5_STATE_THUMB;
                }
        }
 
-       command_print(cmd_ctx, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
+       command_print(CMD_CTX, "core state: %s", armv4_5_state_strings[armv4_5->core_state]);
 
        return ERROR_OK;
 }
@@ -438,31 +453,31 @@ COMMAND_HANDLER(handle_armv4_5_core_state_command)
 COMMAND_HANDLER(handle_armv4_5_disassemble_command)
 {
        int retval = ERROR_OK;
-       struct target *target = get_current_target(cmd_ctx);
+       struct target *target = get_current_target(CMD_CTX);
        struct arm *arm = target ? target_to_arm(target) : NULL;
        uint32_t address;
        int count = 1;
        int thumb = 0;
 
        if (!is_arm(arm)) {
-               command_print(cmd_ctx, "current target isn't an ARM");
+               command_print(CMD_CTX, "current target isn't an ARM");
                return ERROR_FAIL;
        }
 
-       switch (argc) {
+       switch (CMD_ARGC) {
        case 3:
-               if (strcmp(args[2], "thumb") != 0)
+               if (strcmp(CMD_ARGV[2], "thumb") != 0)
                        goto usage;
                thumb = 1;
                /* FALL THROUGH */
        case 2:
-               COMMAND_PARSE_NUMBER(int, args[1], count);
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count);
                /* FALL THROUGH */
        case 1:
-               COMMAND_PARSE_NUMBER(u32, args[0], address);
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
                if (address & 0x01) {
                        if (!thumb) {
-                               command_print(cmd_ctx, "Disassemble as Thumb");
+                               command_print(CMD_CTX, "Disassemble as Thumb");
                                thumb = 1;
                        }
                        address &= ~1;
@@ -470,7 +485,7 @@ COMMAND_HANDLER(handle_armv4_5_disassemble_command)
                break;
        default:
 usage:
-               command_print(cmd_ctx,
+               command_print(CMD_CTX,
                        "usage: arm disassemble <address> [<count> ['thumb']]");
                count = 0;
                retval = ERROR_FAIL;
@@ -499,7 +514,7 @@ usage:
                        if (retval != ERROR_OK)
                                break;
                }
-               command_print(cmd_ctx, "%s", cur_instruction.text);
+               command_print(CMD_CTX, "%s", cur_instruction.text);
                address += cur_instruction.instruction_size;
        }
 
@@ -522,7 +537,8 @@ int armv4_5_register_commands(struct command_context *cmd_ctx)
                        "display/change ARM core state <arm | thumb>");
        register_command(cmd_ctx, armv4_5_cmd, "disassemble",
                        handle_armv4_5_disassemble_command, COMMAND_EXEC,
-                       "disassemble instructions <address> [<count> ['thumb']]");
+                       "disassemble instructions "
+                               "<address> [<count> ['thumb']]");
 
        return ERROR_OK;
 }
@@ -545,10 +561,10 @@ int armv4_5_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int
 
        for (i = 16; i < 24; i++)
        {
-               (*reg_list)[i] = &armv4_5_gdb_dummy_fp_reg;
+               (*reg_list)[i] = &arm_gdb_dummy_fp_reg;
        }
 
-       (*reg_list)[24] = &armv4_5_gdb_dummy_fps_reg;
+       (*reg_list)[24] = &arm_gdb_dummy_fps_reg;
        (*reg_list)[25] = &armv4_5->core_cache->reg_list[ARMV4_5_CPSR];
 
        return ERROR_OK;
@@ -644,13 +660,13 @@ int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struc
                if (!reg)
                {
                        LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
-                       exit(-1);
+                       return ERROR_INVALID_ARGUMENTS;
                }
 
                if (reg->size != reg_params[i].size)
                {
                        LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
-                       exit(-1);
+                       return ERROR_INVALID_ARGUMENTS;
                }
 
                if ((retval = armv4_5_set_core_reg(reg, reg_params[i].value)) != ERROR_OK)
@@ -667,7 +683,7 @@ int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struc
        else
        {
                LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
-               exit(-1);
+               return ERROR_INVALID_ARGUMENTS;
        }
 
        if (armv4_5_algorithm_info->core_mode != ARMV4_5_MODE_ANY)
@@ -717,13 +733,15 @@ int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struc
                        if (!reg)
                        {
                                LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
-                               exit(-1);
+                               retval = ERROR_INVALID_ARGUMENTS;
+                               continue;
                        }
 
                        if (reg->size != reg_params[i].size)
                        {
                                LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
-                               exit(-1);
+                               retval = ERROR_INVALID_ARGUMENTS;
+                               continue;
                        }
 
                        buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));