aboutsummaryrefslogtreecommitdiff
path: root/src/target/nds32.c
diff options
context:
space:
mode:
authorHsiangkai Wang <hsiangkai@gmail.com>2013-05-07 21:43:35 +0800
committerSpencer Oliver <spen@spen-soft.co.uk>2013-08-07 21:00:40 +0000
commitd979d78e97786667d168ba183c9fc60c622d29c1 (patch)
tree19e03565245a64cb7f3138433f78abce8c6acc9a /src/target/nds32.c
parent9f2922aa7abb385d1fb24def91fac7eb4e2304c5 (diff)
gdb_server: support gdb target description
* Add a parameter in .get_gdb_reg_list() to return different register lists as generating target description. * Modify STRUCT REG to let gdb generate target description according to register information. The modified structure of register is struct reg { const char *name; uint32_t number; /* for regnum="num" */ struct reg_feature *feature; /* for register group feature name */ bool caller_save; /* for save-restore="yes|no" */ void *value; bool dirty; bool valid; bool exist; uint32_t size; struct reg_data_type *reg_data_type; /* for type="type" */ const char *group; /* for group="general|float|vector" */ void *arch_info; const struct reg_arch_type *type; }; Change-Id: I2096b67adf94518ba0b8b23d8c6a9f64ad7932b8 Signed-off-by: Hsiangkai Wang <hsiangkai@gmail.com> Reviewed-on: http://openocd.zylin.com/1382 Tested-by: jenkins Reviewed-by: Franck Jullien <franck.jullien@gmail.com> Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk> Reviewed-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
Diffstat (limited to 'src/target/nds32.c')
-rw-r--r--src/target/nds32.c134
1 files changed, 114 insertions, 20 deletions
diff --git a/src/target/nds32.c b/src/target/nds32.c
index 2d477097..95a249d0 100644
--- a/src/target/nds32.c
+++ b/src/target/nds32.c
@@ -91,21 +91,23 @@ static int nds32_get_core_reg(struct reg *reg)
return ERROR_OK;
}
+ int mapped_regnum = nds32->register_map(nds32, reg_arch_info->num);
+
if (reg_arch_info->enable == false) {
reg_arch_info->value = NDS32_REGISTER_DISABLE;
retval = ERROR_FAIL;
} else {
if ((nds32->fpu_enable == false) &&
- (NDS32_REG_TYPE_FPU == nds32_reg_type(reg_arch_info->num))) {
+ (NDS32_REG_TYPE_FPU == nds32_reg_type(mapped_regnum))) {
reg_arch_info->value = 0;
retval = ERROR_OK;
} else if ((nds32->audio_enable == false) &&
- (NDS32_REG_TYPE_AUMR == nds32_reg_type(reg_arch_info->num))) {
+ (NDS32_REG_TYPE_AUMR == nds32_reg_type(mapped_regnum))) {
reg_arch_info->value = 0;
retval = ERROR_OK;
} else {
retval = aice_read_register(aice,
- reg_arch_info->num, &(reg_arch_info->value));
+ mapped_regnum, &(reg_arch_info->value));
}
LOG_DEBUG("reading register %i(%s), value: 0x%8.8" PRIx32,
@@ -301,44 +303,46 @@ static int nds32_set_core_reg(struct reg *reg, uint8_t *buf)
return ERROR_TARGET_NOT_HALTED;
}
+ int mapped_regnum = nds32->register_map(nds32, reg_arch_info->num);
+
/* ignore values that will generate exception */
- if (nds32_reg_exception(reg_arch_info->num, value))
+ if (nds32_reg_exception(mapped_regnum, value))
return ERROR_OK;
LOG_DEBUG("writing register %i(%s) with value 0x%8.8" PRIx32,
reg_arch_info->num, reg->name, value);
if ((nds32->fpu_enable == false) &&
- (NDS32_REG_TYPE_FPU == nds32_reg_type(reg_arch_info->num))) {
+ (NDS32_REG_TYPE_FPU == nds32_reg_type(mapped_regnum))) {
buf_set_u32(reg->value, 0, 32, 0);
} else if ((nds32->audio_enable == false) &&
- (NDS32_REG_TYPE_AUMR == nds32_reg_type(reg_arch_info->num))) {
+ (NDS32_REG_TYPE_AUMR == nds32_reg_type(mapped_regnum))) {
buf_set_u32(reg->value, 0, 32, 0);
} else {
buf_set_u32(reg->value, 0, 32, value);
- aice_write_register(aice, reg_arch_info->num, reg_arch_info->value);
+ aice_write_register(aice, mapped_regnum, reg_arch_info->value);
/* After set value to registers, read the value from target
* to avoid W1C inconsistency. */
- aice_read_register(aice, reg_arch_info->num, &(reg_arch_info->value));
+ aice_read_register(aice, mapped_regnum, &(reg_arch_info->value));
}
reg->valid = true;
reg->dirty = false;
/* update registers to take effect right now */
- if (IR0 == reg_arch_info->num) {
+ if (IR0 == mapped_regnum) {
nds32_update_psw(nds32);
- } else if (MR0 == reg_arch_info->num) {
+ } else if (MR0 == mapped_regnum) {
nds32_update_mmu_info(nds32);
- } else if ((MR6 == reg_arch_info->num) || (MR7 == reg_arch_info->num)) {
+ } else if ((MR6 == mapped_regnum) || (MR7 == mapped_regnum)) {
/* update lm information */
nds32_update_lm_info(nds32);
- } else if (MR8 == reg_arch_info->num) {
+ } else if (MR8 == mapped_regnum) {
nds32_update_cache_info(nds32);
- } else if (FUCPR == reg_arch_info->num) {
+ } else if (FUCPR == mapped_regnum) {
/* update audio/fpu setting */
nds32_check_extension(nds32);
}
@@ -415,17 +419,62 @@ static struct reg_cache *nds32_build_reg_cache(struct target *target,
reg_arch_info[i].enable = false;
reg_list[i].name = nds32_reg_simple_name(i);
+ reg_list[i].number = reg_arch_info[i].num;
reg_list[i].size = nds32_reg_size(i);
reg_list[i].arch_info = &reg_arch_info[i];
+ reg_list[i].reg_data_type = malloc(sizeof(struct reg_data_type));
+
if (FD0 <= reg_arch_info[i].num && reg_arch_info[i].num <= FD31) {
reg_list[i].value = &(reg_arch_info[i].value_64);
reg_list[i].type = &nds32_reg_access_type_64;
+
+ reg_list[i].reg_data_type->type = REG_TYPE_IEEE_DOUBLE;
+ reg_list[i].reg_data_type->id = "ieee_double";
+ reg_list[i].group = "float";
} else {
reg_list[i].value = &(reg_arch_info[i].value);
reg_list[i].type = &nds32_reg_access_type;
+ reg_list[i].group = "general";
+
+ if ((FS0 <= reg_arch_info[i].num) && (reg_arch_info[i].num <= FS31)) {
+ reg_list[i].reg_data_type->type = REG_TYPE_IEEE_SINGLE;
+ reg_list[i].reg_data_type->id = "ieee_single";
+ reg_list[i].group = "float";
+ } else if ((reg_arch_info[i].num == FPCSR) ||
+ (reg_arch_info[i].num == FPCFG)) {
+ reg_list[i].group = "float";
+ } else if ((reg_arch_info[i].num == R28) ||
+ (reg_arch_info[i].num == R29) ||
+ (reg_arch_info[i].num == R31)) {
+ reg_list[i].reg_data_type->type = REG_TYPE_DATA_PTR;
+ reg_list[i].reg_data_type->id = "data_ptr";
+ } else if ((reg_arch_info[i].num == R30) ||
+ (reg_arch_info[i].num == PC)) {
+ reg_list[i].reg_data_type->type = REG_TYPE_CODE_PTR;
+ reg_list[i].reg_data_type->id = "code_ptr";
+ } else {
+ reg_list[i].reg_data_type->type = REG_TYPE_UINT32;
+ reg_list[i].reg_data_type->id = "uint32";
+ }
}
+ if (R16 <= reg_arch_info[i].num && reg_arch_info[i].num <= R25)
+ reg_list[i].caller_save = true;
+ else
+ reg_list[i].caller_save = false;
+
+ reg_list[i].feature = malloc(sizeof(struct reg_feature));
+
+ if (R0 <= reg_arch_info[i].num && reg_arch_info[i].num <= IFC_LP)
+ reg_list[i].feature->name = "org.gnu.gdb.nds32.core";
+ else if (CR0 <= reg_arch_info[i].num && reg_arch_info[i].num <= SECUR0)
+ reg_list[i].feature->name = "org.gnu.gdb.nds32.system";
+ else if (D0L24 <= reg_arch_info[i].num && reg_arch_info[i].num <= CBE3)
+ reg_list[i].feature->name = "org.gnu.gdb.nds32.audio";
+ else if (FPCSR <= reg_arch_info[i].num && reg_arch_info[i].num <= FD31)
+ reg_list[i].feature->name = "org.gnu.gdb.nds32.fpu";
+
cache->num_regs++;
}
@@ -451,9 +500,7 @@ static struct reg *nds32_reg_current(struct nds32 *nds32, unsigned regnum)
{
struct reg *r;
- /* Register mapping, pass user-view registers to gdb */
- int mapped_regnum = nds32->register_map(nds32, regnum);
- r = nds32->core_cache->reg_list + mapped_regnum;
+ r = nds32->core_cache->reg_list + regnum;
return r;
}
@@ -512,12 +559,36 @@ int nds32_set_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t value)
return r->type->set(r, set_value);
}
+/** get general register list */
+static int nds32_get_general_reg_list(struct nds32 *nds32,
+ struct reg **reg_list[], int *reg_list_size)
+{
+ struct reg *reg_current;
+ int i;
+ int current_idx;
+
+ /** freed in gdb_server.c */
+ *reg_list = malloc(sizeof(struct reg *) * (IFC_LP - R0 + 1));
+ current_idx = 0;
+
+ for (i = R0; i < IFC_LP + 1; i++) {
+ reg_current = nds32_reg_current(nds32, i);
+ if (((struct nds32_reg *)reg_current->arch_info)->enable) {
+ (*reg_list)[current_idx] = reg_current;
+ current_idx++;
+ }
+ }
+ *reg_list_size = current_idx;
+
+ return ERROR_OK;
+}
+
/** get all register list */
-int nds32_get_gdb_reg_list(struct target *target,
+static int nds32_get_all_reg_list(struct nds32 *nds32,
struct reg **reg_list[], int *reg_list_size)
{
- struct nds32 *nds32 = target_to_nds32(target);
struct reg_cache *reg_cache = nds32->core_cache;
+ struct reg *reg_current;
unsigned int i;
*reg_list_size = reg_cache->num_regs;
@@ -525,12 +596,35 @@ int nds32_get_gdb_reg_list(struct target *target,
/** freed in gdb_server.c */
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
- for (i = 0; i < reg_cache->num_regs; i++)
- (*reg_list)[i] = nds32_reg_current(nds32, i);
+ for (i = 0; i < reg_cache->num_regs; i++) {
+ reg_current = nds32_reg_current(nds32, i);
+ reg_current->exist = ((struct nds32_reg *)
+ reg_current->arch_info)->enable;
+ (*reg_list)[i] = reg_current;
+ }
return ERROR_OK;
}
+/** get all register list */
+int nds32_get_gdb_reg_list(struct target *target,
+ struct reg **reg_list[], int *reg_list_size,
+ enum target_register_class reg_class)
+{
+ struct nds32 *nds32 = target_to_nds32(target);
+
+ switch (reg_class) {
+ case REG_CLASS_ALL:
+ return nds32_get_all_reg_list(nds32, reg_list, reg_list_size);
+ case REG_CLASS_GENERAL:
+ return nds32_get_general_reg_list(nds32, reg_list, reg_list_size);
+ default:
+ return ERROR_FAIL;
+ }
+
+ return ERROR_FAIL;
+}
+
static int nds32_select_memory_mode(struct target *target, uint32_t address,
uint32_t length, uint32_t *end_address)
{