WIP registers.
This commit is contained in:
parent
ae74097f39
commit
25e8b66b08
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue