// SPDX-License-Identifier: GPL-2.0-or-later /*************************************************************************** * Copyright (C) 2013-2015,2019-2020 Synopsys, Inc. * * Frank Dols * * Mischa Jonker * * Anton Kolesov * * Evgeniy Didin * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "arc.h" /* -------------------------------------------------------------------------- * * ARC targets expose command interface. * It can be accessed via GDB through the (gdb) monitor command. * * ------------------------------------------------------------------------- */ static int arc_cmd_jim_get_uint32(struct jim_getopt_info *goi, uint32_t *value) { jim_wide value_wide; JIM_CHECK_RETVAL(jim_getopt_wide(goi, &value_wide)); *value = (uint32_t)value_wide; return JIM_OK; } enum add_reg_types { CFG_ADD_REG_TYPE_FLAG, CFG_ADD_REG_TYPE_STRUCT, }; /* Add flags register data type */ enum add_reg_type_flags { CFG_ADD_REG_TYPE_FLAGS_NAME, CFG_ADD_REG_TYPE_FLAGS_FLAG, }; static struct jim_nvp nvp_add_reg_type_flags_opts[] = { { .name = "-name", .value = CFG_ADD_REG_TYPE_FLAGS_NAME }, { .name = "-flag", .value = CFG_ADD_REG_TYPE_FLAGS_FLAG }, { .name = NULL, .value = -1 } }; /* Helper function to check if all field required for register * are set up */ static const char *validate_register(const struct arc_reg_desc * const reg, bool arch_num_set) { /* Check that required fields are set */ if (!reg->name) return "-name option is required"; if (!reg->gdb_xml_feature) return "-feature option is required"; if (!arch_num_set) return "-num option is required"; if (reg->is_bcr && reg->is_core) return "Register cannot be both -core and -bcr."; return NULL; } /* Helper function to read the name of register type or register from * configure files */ static int jim_arc_read_reg_name_field(struct jim_getopt_info *goi, const char **name, int *name_len) { int e = JIM_OK; if (!goi->argc) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-name ..."); return JIM_ERR; } e = jim_getopt_string(goi, name, name_len); return e; } /* Helper function to read bitfields/flags of register type. */ static int jim_arc_read_reg_type_field(struct jim_getopt_info *goi, const char **field_name, int *field_name_len, struct arc_reg_bitfield *bitfields, int cur_field, int type) { jim_wide start_pos, end_pos; int e = JIM_OK; if ((type == CFG_ADD_REG_TYPE_STRUCT && goi->argc < 3) || (type == CFG_ADD_REG_TYPE_FLAG && goi->argc < 2)) { Jim_SetResultFormatted(goi->interp, "Not enough arguments after -flag/-bitfield"); return JIM_ERR; } e = jim_getopt_string(goi, field_name, field_name_len); if (e != JIM_OK) return e; /* read start position of bitfield/flag */ e = jim_getopt_wide(goi, &start_pos); if (e != JIM_OK) return e; end_pos = start_pos; /* Check if any arguments remain, * set bitfields[cur_field].end if flag is multibit */ if (goi->argc > 0) /* Check current argv[0], if it is equal to "-flag", * than bitfields[cur_field].end remains start */ if ((strcmp(Jim_String(goi->argv[0]), "-flag") && type == CFG_ADD_REG_TYPE_FLAG) || (type == CFG_ADD_REG_TYPE_STRUCT)) { e = jim_getopt_wide(goi, &end_pos); if (e != JIM_OK) { Jim_SetResultFormatted(goi->interp, "Error reading end position"); return e; } } bitfields[cur_field].bitfield.start = start_pos; bitfields[cur_field].bitfield.end = end_pos; if ((end_pos != start_pos) || (type == CFG_ADD_REG_TYPE_STRUCT)) bitfields[cur_field].bitfield.type = REG_TYPE_INT; return e; } static int jim_arc_add_reg_type_flags(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { struct jim_getopt_info goi; JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1)); LOG_DEBUG("-"); struct command_context *ctx; struct target *target; ctx = current_command_context(interp); assert(ctx); target = get_current_target(ctx); if (!target) { Jim_SetResultFormatted(goi.interp, "No current target"); return JIM_ERR; } int e = JIM_OK; /* Check if the amount of arguments is not zero */ if (goi.argc <= 0) { Jim_SetResultFormatted(goi.interp, "The command has no arguments"); return JIM_ERR; } /* Estimate number of registers as (argc - 2)/3 as each -flag option has 2 * arguments while -name is required. */ unsigned int fields_sz = (goi.argc - 2) / 3; unsigned int cur_field = 0; /* The maximum amount of bitfields is 32 */ if (fields_sz > 32) { Jim_SetResultFormatted(goi.interp, "The amount of bitfields exceed 32"); return JIM_ERR; } struct arc_reg_data_type *type = calloc(1, sizeof(*type)); struct reg_data_type_flags *flags = &type->data_type_flags; struct reg_data_type_flags_field *fields = calloc(fields_sz, sizeof(*fields)); type->reg_type_flags_field = fields; struct arc_reg_bitfield *bitfields = calloc(fields_sz, sizeof(*bitfields)); if (!(type && fields && bitfields)) { Jim_SetResultFormatted(goi.interp, "Failed to allocate memory."); goto fail; } /* Initialize type */ type->bitfields = bitfields; type->data_type.id = type->data_type_id; type->data_type.type = REG_TYPE_ARCH_DEFINED; type->data_type.type_class = REG_TYPE_CLASS_FLAGS; type->data_type.reg_type_flags = flags; flags->size = 4; /* For now ARC has only 32-bit registers */ while (goi.argc > 0 && e == JIM_OK) { struct jim_nvp *n; e = jim_getopt_nvp(&goi, nvp_add_reg_type_flags_opts, &n); if (e != JIM_OK) { jim_getopt_nvp_unknown(&goi, nvp_add_reg_type_flags_opts, 0); continue; } switch (n->value) { case CFG_ADD_REG_TYPE_FLAGS_NAME: { const char *name = NULL; int name_len = 0; e = jim_arc_read_reg_name_field(&goi, &name, &name_len); if (e != JIM_OK) { Jim_SetResultFormatted(goi.interp, "Unable to read reg name."); goto fail; } if (name_len > REG_TYPE_MAX_NAME_LENGTH) { Jim_SetResultFormatted(goi.interp, "Reg type name is too big."); goto fail; } strncpy((void *)type->data_type.id, name, name_len); if (!type->data_type.id) { Jim_SetResultFormatted(goi.interp, "Unable to setup reg type name."); goto fail; } break; } case CFG_ADD_REG_TYPE_FLAGS_FLAG: { const char *field_name = NULL; int field_name_len = 0; e = jim_arc_read_reg_type_field(&goi, &field_name, &field_name_len, bitfields, cur_field, CFG_ADD_REG_TYPE_FLAG); if (e != JIM_OK) { Jim_SetResultFormatted(goi.interp, "Unable to add reg_type_flag field."); goto fail; } if (field_name_len > REG_TYPE_MAX_NAME_LENGTH) { Jim_SetResultFormatted(goi.interp, "Reg type field_name_len is too big."); goto fail; } fields[cur_field].name = bitfields[cur_field].name; strncpy(bitfields[cur_field].name, field_name, field_name_len); if (!fields[cur_field].name) { Jim_SetResultFormatted(goi.interp, "Unable to setup field name. "); goto fail; } fields[cur_field].bitfield = &(bitfields[cur_field].bitfield); if (cur_field > 0) fields[cur_field - 1].next = &(fields[cur_field]); else flags->fields = fields; cur_field += 1; break; } } } if (!type->data_type.id) { Jim_SetResultFormatted(goi.interp, "-name is a required option"); goto fail; } arc_reg_data_type_add(target, type); LOG_DEBUG("added flags type {name=%s}", type->data_type.id); return JIM_OK; fail: free(type); free(fields); free(bitfields); return JIM_ERR; } /* Add struct register data type */ enum add_reg_type_struct { CFG_ADD_REG_TYPE_STRUCT_NAME, CFG_ADD_REG_TYPE_STRUCT_BITFIELD, }; static struct jim_nvp nvp_add_reg_type_struct_opts[] = { { .name = "-name", .value = CFG_ADD_REG_TYPE_STRUCT_NAME }, { .name = "-bitfield", .value = CFG_ADD_REG_TYPE_STRUCT_BITFIELD }, { .name = NULL, .value = -1 } }; static int jim_arc_set_aux_reg(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { struct command_context *context; struct target *target; uint32_t regnum; uint32_t value; struct jim_getopt_info goi; JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1)); if (goi.argc != 2) { Jim_SetResultFormatted(goi.interp, "usage: %s ", Jim_GetString(argv[0], NULL)); return JIM_ERR; } context = current_command_context(interp); assert(context); target = get_current_target(context); if (!target) { Jim_SetResultFormatted(goi.interp, "No current target"); return JIM_ERR; } /* Register number */ JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, ®num)); /* Register value */ JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, &value)); struct arc_common *arc = target_to_arc(target); assert(arc); CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, regnum, value)); return ERROR_OK; } static int jim_arc_get_aux_reg(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { struct command_context *context; struct target *target; uint32_t regnum; uint32_t value; struct jim_getopt_info goi; JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1)); if (goi.argc != 1) { Jim_SetResultFormatted(goi.interp, "usage: %s ", Jim_GetString(argv[0], NULL)); return JIM_ERR; } context = current_command_context(interp); assert(context); target = get_current_target(context); if (!target) { Jim_SetResultFormatted(goi.interp, "No current target"); return JIM_ERR; } /* Register number */ JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, ®num)); struct arc_common *arc = target_to_arc(target); assert(arc); CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, regnum, &value)); Jim_SetResultInt(interp, value); return ERROR_OK; } static int jim_arc_get_core_reg(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { struct command_context *context; struct target *target; uint32_t regnum; uint32_t value; struct jim_getopt_info goi; JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1)); if (goi.argc != 1) { Jim_SetResultFormatted(goi.interp, "usage: %s ", Jim_GetString(argv[0], NULL)); return JIM_ERR; } context = current_command_context(interp); assert(context); target = get_current_target(context); if (!target) { Jim_SetResultFormatted(goi.interp, "No current target"); return JIM_ERR; } /* Register number */ JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, ®num)); if (regnum > CORE_REG_MAX_NUMBER || regnum == ARC_R61 || regnum == ARC_R62) { Jim_SetResultFormatted(goi.interp, "Core register number %i " "is invalid. Must less then 64 and not 61 and 62.", regnum); return JIM_ERR; } struct arc_common *arc = target_to_arc(target); assert(arc); /* Read value */ CHECK_RETVAL(arc_jtag_read_core_reg_one(&arc->jtag_info, regnum, &value)); Jim_SetResultInt(interp, value); return ERROR_OK; } static int jim_arc_set_core_reg(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { struct command_context *context; struct target *target; uint32_t regnum; uint32_t value; struct jim_getopt_info goi; JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1)); if (goi.argc != 2) { Jim_SetResultFormatted(goi.interp, "usage: %s ", Jim_GetString(argv[0], NULL)); return JIM_ERR; } context = current_command_context(interp); assert(context); target = get_current_target(context); if (!target) { Jim_SetResultFormatted(goi.interp, "No current target"); return JIM_ERR; } /* Register number */ JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, ®num)); if (regnum > CORE_REG_MAX_NUMBER || regnum == ARC_R61 || regnum == ARC_R62) { Jim_SetResultFormatted(goi.interp, "Core register number %i " "is invalid. Must less then 64 and not 61 and 62.", regnum); return JIM_ERR; } /* Register value */ JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, &value)); struct arc_common *arc = target_to_arc(target); assert(arc); CHECK_RETVAL(arc_jtag_write_core_reg_one(&arc->jtag_info, regnum, value)); return ERROR_OK; } static const struct command_registration arc_jtag_command_group[] = { { .name = "get-aux-reg", .jim_handler = jim_arc_get_aux_reg, .mode = COMMAND_EXEC, .help = "Get AUX register by number. This command does a " "raw JTAG request that bypasses OpenOCD register cache " "and thus is unsafe and can have unexpected consequences. " "Use at your own risk.", .usage = "" }, { .name = "set-aux-reg", .jim_handler = jim_arc_set_aux_reg, .mode = COMMAND_EXEC, .help = "Set AUX register by number. This command does a " "raw JTAG request that bypasses OpenOCD register cache " "and thus is unsafe and can have unexpected consequences. " "Use at your own risk.", .usage = " " }, { .name = "get-core-reg", .jim_handler = jim_arc_get_core_reg, .mode = COMMAND_EXEC, .help = "Get/Set core register by number. This command does a " "raw JTAG request that bypasses OpenOCD register cache " "and thus is unsafe and can have unexpected consequences. " "Use at your own risk.", .usage = " []" }, { .name = "set-core-reg", .jim_handler = jim_arc_set_core_reg, .mode = COMMAND_EXEC, .help = "Get/Set core register by number. This command does a " "raw JTAG request that bypasses OpenOCD register cache " "and thus is unsafe and can have unexpected consequences. " "Use at your own risk.", .usage = " []" }, COMMAND_REGISTRATION_DONE }; /* This function supports only bitfields. */ static int jim_arc_add_reg_type_struct(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { struct jim_getopt_info goi; JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1)); LOG_DEBUG("-"); struct command_context *ctx; struct target *target; ctx = current_command_context(interp); assert(ctx); target = get_current_target(ctx); if (!target) { Jim_SetResultFormatted(goi.interp, "No current target"); return JIM_ERR; } int e = JIM_OK; /* Check if the amount of arguments is not zero */ if (goi.argc <= 0) { Jim_SetResultFormatted(goi.interp, "The command has no arguments"); return JIM_ERR; } /* Estimate number of registers as (argc - 2)/4 as each -bitfield option has 3 * arguments while -name is required. */ unsigned int fields_sz = (goi.argc - 2) / 4; unsigned int cur_field = 0; /* The maximum amount of bitfields is 32 */ if (fields_sz > 32) { Jim_SetResultFormatted(goi.interp, "The amount of bitfields exceed 32"); return JIM_ERR; } struct arc_reg_data_type *type = calloc(1, sizeof(*type)); struct reg_data_type_struct *struct_type = &type->data_type_struct; struct reg_data_type_struct_field *fields = calloc(fields_sz, sizeof(*fields)); type->reg_type_struct_field = fields; struct arc_reg_bitfield *bitfields = calloc(fields_sz, sizeof(*bitfields)); if (!(type && fields && bitfields)) { Jim_SetResultFormatted(goi.interp, "Failed to allocate memory."); goto fail; } /* Initialize type */ type->data_type.id = type->data_type_id; type->bitfields = bitfields; type->data_type.type = REG_TYPE_ARCH_DEFINED; type->data_type.type_class = REG_TYPE_CLASS_STRUCT; type->data_type.reg_type_struct = struct_type; struct_type->size = 4; /* For now ARC has only 32-bit registers */ while (goi.argc > 0 && e == JIM_OK) { struct jim_nvp *n; e = jim_getopt_nvp(&goi, nvp_add_reg_type_struct_opts, &n); if (e != JIM_OK) { jim_getopt_nvp_unknown(&goi, nvp_add_reg_type_struct_opts, 0); continue; } switch (n->value) { case CFG_ADD_REG_TYPE_STRUCT_NAME: { const char *name = NULL; int name_len = 0; e = jim_arc_read_reg_name_field(&goi, &name, &name_len); if (e != JIM_OK) { Jim_SetResultFormatted(goi.interp, "Unable to read reg name."); goto fail; } if (name_len > REG_TYPE_MAX_NAME_LENGTH) { Jim_SetResultFormatted(goi.interp, "Reg type name is too big."); goto fail; } strncpy((void *)type->data_type.id, name, name_len); if (!type->data_type.id) { Jim_SetResultFormatted(goi.interp, "Unable to setup reg type name."); goto fail; } break; } case CFG_ADD_REG_TYPE_STRUCT_BITFIELD: { const char *field_name = NULL; int field_name_len = 0; e = jim_arc_read_reg_type_field(&goi, &field_name, &field_name_len, bitfields, cur_field, CFG_ADD_REG_TYPE_STRUCT); if (e != JIM_OK) { Jim_SetResultFormatted(goi.interp, "Unable to add reg_type_struct field."); goto fail; } if (field_name_len > REG_TYPE_MAX_NAME_LENGTH) { Jim_SetResultFormatted(goi.interp, "Reg type field_name_len is too big."); goto fail; } fields[cur_field].name = bitfields[cur_field].name; strncpy(bitfields[cur_field].name, field_name, field_name_len); if (!fields[cur_field].name) { Jim_SetResultFormatted(goi.interp, "Unable to setup field name. "); goto fail; } fields[cur_field].bitfield = &(bitfields[cur_field].bitfield); fields[cur_field].use_bitfields = true; if (cur_field > 0) fields[cur_field - 1].next = &(fields[cur_field]); else struct_type->fields = fields; cur_field += 1; break; } } } if (!type->data_type.id) { Jim_SetResultFormatted(goi.interp, "-name is a required option"); goto fail; } arc_reg_data_type_add(target, type); LOG_DEBUG("added struct type {name=%s}", type->data_type.id); return JIM_OK; fail: free(type); free(fields); free(bitfields); return JIM_ERR; } /* Add register */ enum opts_add_reg { CFG_ADD_REG_NAME, CFG_ADD_REG_ARCH_NUM, CFG_ADD_REG_IS_CORE, CFG_ADD_REG_IS_BCR, CFG_ADD_REG_GDB_FEATURE, CFG_ADD_REG_TYPE, CFG_ADD_REG_GENERAL, }; static struct jim_nvp opts_nvp_add_reg[] = { { .name = "-name", .value = CFG_ADD_REG_NAME }, { .name = "-num", .value = CFG_ADD_REG_ARCH_NUM }, { .name = "-core", .value = CFG_ADD_REG_IS_CORE }, { .name = "-bcr", .value = CFG_ADD_REG_IS_BCR }, { .name = "-feature", .value = CFG_ADD_REG_GDB_FEATURE }, { .name = "-type", .value = CFG_ADD_REG_TYPE }, { .name = "-g", .value = CFG_ADD_REG_GENERAL }, { .name = NULL, .value = -1 } }; void free_reg_desc(struct arc_reg_desc *r) { free(r->name); free(r->gdb_xml_feature); free(r); } static int jim_arc_add_reg(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { struct jim_getopt_info goi; JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1)); struct arc_reg_desc *reg = calloc(1, sizeof(*reg)); if (!reg) { Jim_SetResultFormatted(goi.interp, "Failed to allocate memory."); return JIM_ERR; } /* There is no architecture number that we could treat as invalid, so * separate variable required to ensure that arch num has been set. */ bool arch_num_set = false; const char *type_name = "int"; /* Default type */ int type_name_len = strlen(type_name); int e = ERROR_OK; /* At least we need to specify 4 parameters: name, number and gdb_feature, * which means there should be 6 arguments. Also there can be additional parameters * "-type ", "-g" and "-core" or "-bcr" which makes maximum 10 parameters. */ if (goi.argc < 6 || goi.argc > 10) { free_reg_desc(reg); Jim_SetResultFormatted(goi.interp, "Should be at least 6 arguments and not greater than 10: " " -name -num -feature " " [-type ] [-core|-bcr] [-g]."); return JIM_ERR; } /* Parse options. */ while (goi.argc > 0) { struct jim_nvp *n; e = jim_getopt_nvp(&goi, opts_nvp_add_reg, &n); if (e != JIM_OK) { jim_getopt_nvp_unknown(&goi, opts_nvp_add_reg, 0); free_reg_desc(reg); return e; } switch (n->value) { case CFG_ADD_REG_NAME: { const char *reg_name = NULL; int reg_name_len = 0; e = jim_arc_read_reg_name_field(&goi, ®_name, ®_name_len); if (e != JIM_OK) { Jim_SetResultFormatted(goi.interp, "Unable to read register name."); free_reg_desc(reg); return e; } reg->name = strndup(reg_name, reg_name_len); break; } case CFG_ADD_REG_IS_CORE: reg->is_core = true; break; case CFG_ADD_REG_IS_BCR: reg->is_bcr = true; break; case CFG_ADD_REG_ARCH_NUM: { jim_wide archnum; if (!goi.argc) { free_reg_desc(reg); Jim_WrongNumArgs(interp, goi.argc, goi.argv, "-num ..."); return JIM_ERR; } e = jim_getopt_wide(&goi, &archnum); if (e != JIM_OK) { free_reg_desc(reg); return e; } reg->arch_num = archnum; arch_num_set = true; break; } case CFG_ADD_REG_GDB_FEATURE: { const char *feature = NULL; int feature_len = 0; e = jim_arc_read_reg_name_field(&goi, &feature, &feature_len); if (e != JIM_OK) { Jim_SetResultFormatted(goi.interp, "Unable to read gdb_feature."); free_reg_desc(reg); return e; } reg->gdb_xml_feature = strndup(feature, feature_len); break; } case CFG_ADD_REG_TYPE: e = jim_arc_read_reg_name_field(&goi, &type_name, &type_name_len); if (e != JIM_OK) { Jim_SetResultFormatted(goi.interp, "Unable to read register type."); free_reg_desc(reg); return e; } break; case CFG_ADD_REG_GENERAL: reg->is_general = true; break; default: LOG_DEBUG("Error: Unknown parameter"); free_reg_desc(reg); return JIM_ERR; } } /* Check that required fields are set */ const char * const errmsg = validate_register(reg, arch_num_set); if (errmsg) { Jim_SetResultFormatted(goi.interp, errmsg); free_reg_desc(reg); return JIM_ERR; } /* Add new register */ struct command_context *ctx; struct target *target; ctx = current_command_context(interp); assert(ctx); target = get_current_target(ctx); if (!target) { Jim_SetResultFormatted(goi.interp, "No current target"); free_reg_desc(reg); return JIM_ERR; } reg->target = target; e = arc_reg_add(target, reg, type_name, type_name_len); if (e == ERROR_ARC_REGTYPE_NOT_FOUND) { Jim_SetResultFormatted(goi.interp, "Cannot find type `%s' for register `%s'.", type_name, reg->name); free_reg_desc(reg); return JIM_ERR; } return e; } /* arc set-reg-exists ($reg_name)+ * Accepts any amount of register names - will set them as existing in a loop.*/ COMMAND_HANDLER(arc_set_reg_exists) { struct target * const target = get_current_target(CMD_CTX); if (!target) { command_print(CMD, "Unable to get current target."); return JIM_ERR; } if (!CMD_ARGC) { command_print(CMD, "At least one register name must be specified."); return ERROR_COMMAND_SYNTAX_ERROR; } for (unsigned int i = 0; i < CMD_ARGC; i++) { const char * const reg_name = CMD_ARGV[i]; struct reg * const r = arc_reg_get_by_name(target->reg_cache, reg_name, true); if (!r) { command_print(CMD, "Register `%s' is not found.", reg_name); return ERROR_COMMAND_ARGUMENT_INVALID; } r->exist = true; } return JIM_OK; } /* arc reg-field ($reg_name) ($reg_field) * Reads struct type register field */ static int jim_arc_get_reg_field(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { struct jim_getopt_info goi; const char *reg_name, *field_name; uint32_t value; int retval; JIM_CHECK_RETVAL(jim_getopt_setup(&goi, interp, argc-1, argv+1)); LOG_DEBUG("Reading register field"); if (goi.argc != 2) { if (!goi.argc) Jim_WrongNumArgs(interp, goi.argc, goi.argv, " "); else if (goi.argc == 1) Jim_WrongNumArgs(interp, goi.argc, goi.argv, ""); else Jim_WrongNumArgs(interp, goi.argc, goi.argv, " "); return ERROR_COMMAND_SYNTAX_ERROR; } JIM_CHECK_RETVAL(jim_getopt_string(&goi, ®_name, NULL)); JIM_CHECK_RETVAL(jim_getopt_string(&goi, &field_name, NULL)); assert(reg_name); assert(field_name); struct command_context * const ctx = current_command_context(interp); assert(ctx); struct target * const target = get_current_target(ctx); if (!target) { Jim_SetResultFormatted(goi.interp, "No current target"); return JIM_ERR; } retval = arc_reg_get_field(target, reg_name, field_name, &value); switch (retval) { case ERROR_OK: break; case ERROR_ARC_REGISTER_NOT_FOUND: Jim_SetResultFormatted(goi.interp, "Register `%s' has not been found.", reg_name); return ERROR_COMMAND_ARGUMENT_INVALID; case ERROR_ARC_REGISTER_IS_NOT_STRUCT: Jim_SetResultFormatted(goi.interp, "Register `%s' must have 'struct' type.", reg_name); return ERROR_COMMAND_ARGUMENT_INVALID; case ERROR_ARC_REGISTER_FIELD_NOT_FOUND: Jim_SetResultFormatted(goi.interp, "Field `%s' has not been found in register `%s'.", field_name, reg_name); return ERROR_COMMAND_ARGUMENT_INVALID; case ERROR_ARC_FIELD_IS_NOT_BITFIELD: Jim_SetResultFormatted(goi.interp, "Field `%s' is not a 'bitfield' field in a structure.", field_name); return ERROR_COMMAND_ARGUMENT_INVALID; default: /* Pass through other errors. */ return retval; } Jim_SetResultInt(interp, value); return JIM_OK; } COMMAND_HANDLER(arc_l1_cache_disable_auto_cmd) { bool value; int retval = 0; struct arc_common *arc = target_to_arc(get_current_target(CMD_CTX)); retval = CALL_COMMAND_HANDLER(handle_command_parse_bool, &value, "target has caches enabled"); arc->has_l2cache = value; arc->has_dcache = value; arc->has_icache = value; return retval; } COMMAND_HANDLER(arc_l2_cache_disable_auto_cmd) { struct arc_common *arc = target_to_arc(get_current_target(CMD_CTX)); return CALL_COMMAND_HANDLER(handle_command_parse_bool, &arc->has_l2cache, "target has l2 cache enabled"); } static int jim_handle_actionpoints_num(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { struct jim_getopt_info goi; jim_getopt_setup(&goi, interp, argc - 1, argv + 1); LOG_DEBUG("-"); if (goi.argc >= 2) { Jim_WrongNumArgs(interp, goi.argc, goi.argv, "[]"); return JIM_ERR; } struct command_context *context = current_command_context(interp); assert(context); struct target *target = get_current_target(context); if (!target) { Jim_SetResultFormatted(goi.interp, "No current target"); return JIM_ERR; } struct arc_common *arc = target_to_arc(target); /* It is not possible to pass &arc->actionpoints_num directly to * handle_command_parse_uint, because this value should be valid during * "actionpoint reset, initiated by arc_set_actionpoints_num. */ uint32_t ap_num = arc->actionpoints_num; if (goi.argc == 1) { JIM_CHECK_RETVAL(arc_cmd_jim_get_uint32(&goi, &ap_num)); int e = arc_set_actionpoints_num(target, ap_num); if (e != ERROR_OK) { Jim_SetResultFormatted(goi.interp, "Failed to set number of actionpoints"); return JIM_ERR; } } Jim_SetResultInt(interp, ap_num); return JIM_OK; } /* ----- Exported target commands ------------------------------------------ */ static const struct command_registration arc_l2_cache_group_handlers[] = { { .name = "auto", .handler = arc_l2_cache_disable_auto_cmd, .mode = COMMAND_ANY, .usage = "(1|0)", .help = "Disable or enable L2", }, COMMAND_REGISTRATION_DONE }; static const struct command_registration arc_cache_group_handlers[] = { { .name = "auto", .handler = arc_l1_cache_disable_auto_cmd, .mode = COMMAND_ANY, .help = "Disable or enable L1", .usage = "(1|0)", }, { .name = "l2", .mode = COMMAND_ANY, .help = "L2 cache command group", .usage = "", .chain = arc_l2_cache_group_handlers, }, COMMAND_REGISTRATION_DONE }; static const struct command_registration arc_core_command_handlers[] = { { .name = "add-reg-type-flags", .jim_handler = jim_arc_add_reg_type_flags, .mode = COMMAND_CONFIG, .usage = "-name -flag " "[-flag ]...", .help = "Add new 'flags' register data type. Only single bit flags " "are supported. Type name is global. Bitsize of register is fixed " "at 32 bits.", }, { .name = "add-reg-type-struct", .jim_handler = jim_arc_add_reg_type_struct, .mode = COMMAND_CONFIG, .usage = "-name -bitfield " "[-bitfield ]...", .help = "Add new 'struct' register data type. Only bit-fields are " "supported so far, which means that for each bitfield start and end " "position bits must be specified. GDB also support type-fields, " "where common type can be used instead. Type name is global. Bitsize of " "register is fixed at 32 bits.", }, { .name = "add-reg", .jim_handler = jim_arc_add_reg, .mode = COMMAND_CONFIG, .usage = "-name -num -feature [-gdbnum ] " "[-core|-bcr] [-type ] [-g]", .help = "Add new register. Name, architectural number and feature name " "are required options. GDB regnum will default to previous register " "(gdbnum + 1) and shouldn't be specified in most cases. Type " "defaults to default GDB 'int'.", }, { .name = "set-reg-exists", .handler = arc_set_reg_exists, .mode = COMMAND_ANY, .usage = " []...", .help = "Set that register exists. Accepts multiple register names as " "arguments.", }, { .name = "get-reg-field", .jim_handler = jim_arc_get_reg_field, .mode = COMMAND_ANY, .usage = " ", .help = "Returns value of field in a register with 'struct' type.", }, { .name = "jtag", .mode = COMMAND_ANY, .help = "ARC JTAG specific commands", .usage = "", .chain = arc_jtag_command_group, }, { .name = "cache", .mode = COMMAND_ANY, .help = "cache command group", .usage = "", .chain = arc_cache_group_handlers, }, { .name = "num-actionpoints", .jim_handler = jim_handle_actionpoints_num, .mode = COMMAND_ANY, .usage = "[]", .help = "Prints or sets amount of actionpoints in the processor.", }, COMMAND_REGISTRATION_DONE }; const struct command_registration arc_monitor_command_handlers[] = { { .name = "arc", .mode = COMMAND_ANY, .help = "ARC monitor command group", .usage = "", .chain = arc_core_command_handlers, }, COMMAND_REGISTRATION_DONE };