WIP registers.

This commit is contained in:
Tim Newsome 2016-05-31 12:12:24 -07:00
parent ae74097f39
commit 25e8b66b08
2 changed files with 41 additions and 7 deletions

View File

@ -118,11 +118,12 @@ struct reg {
const char *name; const char *name;
/** Number that gdb uses to access this register. */ /** Number that gdb uses to access this register. */
uint32_t number; uint32_t number;
/* TODO */ /* TODO. This should probably be const. */
struct reg_feature *feature; struct reg_feature *feature;
/* TODO: When true, the caller will save this register before running any algorithm. */ /* TODO: When true, the caller will save this register before running any algorithm. */
bool caller_save; bool caller_save;
/* TODO */ /* Pointer to place where the value is stored, in the format understood by
* the binarybuffer.h functions. */
void *value; void *value;
/* The stored value needs to be written to the target. */ /* The stored value needs to be written to the target. */
bool dirty; bool dirty;
@ -132,9 +133,11 @@ struct reg {
bool exist; bool exist;
/* Size of the register in bits. */ /* Size of the register in bits. */
uint32_t size; uint32_t size;
/* TODO */ /* Used for generating XML description of registers. Can be set to NULL for
* targets that don't use that. */
struct reg_data_type *reg_data_type; struct reg_data_type *reg_data_type;
/* TODO */ /* Used for generating XML description of registers. Can be set to NULL for
* targets that don't use that. */
const char *group; const char *group;
/* Pointer to architecture-specific info for this register. */ /* Pointer to architecture-specific info for this register. */
void *arch_info; void *arch_info;

View File

@ -114,6 +114,8 @@ typedef struct {
/* Single buffer that contains all register names, instead of calling /* Single buffer that contains all register names, instead of calling
* malloc for each register. Needs to be freed when reg_list is freed. */ * malloc for each register. Needs to be freed when reg_list is freed. */
char *reg_names; char *reg_names;
/* Single buffer that contains all register values. */
void *reg_values;
} riscv_info_t; } riscv_info_t;
typedef struct { typedef struct {
@ -371,6 +373,26 @@ static int resume(struct target *target, int current, uint32_t address,
return ERROR_OK; return ERROR_OK;
} }
/** Update register sizes based on xlen. */
static void update_reg_list(struct target *target)
{
riscv_info_t *info = (riscv_info_t *) target->arch_info;
if (info->reg_values) {
free(info->reg_values);
}
info->reg_values = malloc(REG_COUNT * info->xlen / 4);
for (unsigned int i = 0; i < REG_COUNT; i++) {
struct reg *r = &info->reg_list[i];
r->value = info->reg_values + i * info->xlen / 4;
r->size = info->xlen;
if (r->dirty) {
LOG_ERROR("Register %d was dirty. Its value is lost.", i);
}
r->valid = false;
}
}
/*** OpenOCD target functions. ***/ /*** OpenOCD target functions. ***/
static int riscv_init_target(struct command_context *cmd_ctx, static int riscv_init_target(struct command_context *cmd_ctx,
@ -392,20 +414,27 @@ static int riscv_init_target(struct command_context *cmd_ctx,
info->reg_names = malloc(REG_COUNT * max_reg_name_len); info->reg_names = malloc(REG_COUNT * max_reg_name_len);
char *reg_name = info->reg_names; char *reg_name = info->reg_names;
info->reg_values = NULL;
static struct reg_feature feature_general = {"general"};
// TODO TODO // TODO TODO
for (unsigned int i = 0; i < REG_COUNT; i++) { for (unsigned int i = 0; i < REG_COUNT; i++) {
struct reg *r = &info->reg_list[i]; struct reg *r = &info->reg_list[i];
r->number = i; r->number = i;
r->caller_save = true; r->caller_save = true;
r->dirty = false;
r->valid = false;
r->exist = true;
if (i <= REG_XPR31) { if (i <= REG_XPR31) {
sprintf(reg_name, "x%d", i); sprintf(reg_name, "x%d", i);
r->name = reg_name; r->name = reg_name;
// TODO r->feature = "general"; r->feature = &feature_general;
} }
reg_name += strlen(reg_name) + 1; reg_name += strlen(reg_name) + 1;
assert(reg_name < info->reg_names + REG_COUNT * max_reg_name_len); assert(reg_name < info->reg_names + REG_COUNT * max_reg_name_len);
} }
update_reg_list(target);
return ERROR_OK; return ERROR_OK;
} }
@ -468,7 +497,7 @@ static int riscv_examine(struct target *target)
if (wait_for_debugint_clear(target) != ERROR_OK) { if (wait_for_debugint_clear(target) != ERROR_OK) {
LOG_ERROR("Debug interrupt didn't clear."); LOG_ERROR("Debug interrupt didn't clear.");
return ERROR_FAIL; // TODO: return ERROR_FAIL;
} }
uint32_t word0 = dram_read32(target, 0, false); uint32_t word0 = dram_read32(target, 0, false);
@ -482,8 +511,10 @@ static int riscv_examine(struct target *target)
} else { } else {
LOG_ERROR("Failed to discover xlen; word0=0x%x, word1=0x%x", LOG_ERROR("Failed to discover xlen; word0=0x%x, word1=0x%x",
word0, word1); word0, word1);
return ERROR_FAIL; // TODO: return ERROR_FAIL;
} }
// Update register list to match discovered XLEN.
update_reg_list(target);
target_set_examined(target); target_set_examined(target);