ARM11: don't expose DSCR

Remove the remaining extra copy of DSCR, and the register cache
of which it was a part.  That cache wasn't a very safe, or even
necessary, idea; it was essentialy letting debugger-private state
be manipulated by Tcl code that couldn't know how to do it right.

This makes the "reg" output of an ARM11 resemble what most other
ARM cores produce ... forward motion in the "make ARM11 work like
the rest of the ARM cores" Jihad!
This commit is contained in:
David Brownell 2009-12-02 22:57:08 -08:00
parent f0c3e7011f
commit d5e4e23f9a
2 changed files with 7 additions and 185 deletions

View File

@ -46,41 +46,8 @@ static uint32_t arm11_vcr = 0;
static bool arm11_config_step_irq_enable = false; static bool arm11_config_step_irq_enable = false;
static bool arm11_config_hardware_step = false; static bool arm11_config_hardware_step = false;
enum arm11_regtype
{
/* debug regs */
ARM11_REGISTER_DSCR,
};
struct arm11_reg_defs
{
char * name;
uint32_t num;
int gdb_num;
enum arm11_regtype type;
};
/* update arm11_regcache_ids when changing this */
static const struct arm11_reg_defs arm11_reg_defs[] =
{
/* Debug Registers */
{"dscr", 0, -1, ARM11_REGISTER_DSCR},
};
enum arm11_regcache_ids
{
ARM11_RC_DSCR,
ARM11_RC_MAX,
};
static int arm11_step(struct target *target, int current, static int arm11_step(struct target *target, int current,
uint32_t address, int handle_breakpoints); uint32_t address, int handle_breakpoints);
/* helpers */
static int arm11_build_reg_cache(struct target *target);
static int arm11_set_reg(struct reg *reg, uint8_t *buf);
static int arm11_get_reg(struct reg *reg);
/** Check and if necessary take control of the system /** Check and if necessary take control of the system
@ -127,11 +94,6 @@ static int arm11_check_init(struct arm11_common *arm11)
return ERROR_OK; return ERROR_OK;
} }
#define R(x) \
(arm11->reg_values[ARM11_RC_##x])
/** /**
* Save processor state. This is called after a HALT instruction * Save processor state. This is called after a HALT instruction
* succeeds, and on other occasions the processor enters debug mode * succeeds, and on other occasions the processor enters debug mode
@ -148,17 +110,8 @@ static int arm11_debug_entry(struct arm11_common *arm11)
/* REVISIT entire cache should already be invalid !!! */ /* REVISIT entire cache should already be invalid !!! */
register_cache_invalidate(arm11->arm.core_cache); register_cache_invalidate(arm11->arm.core_cache);
for (size_t i = 0; i < ARRAY_SIZE(arm11->reg_values); i++)
{
arm11->reg_list[i].valid = 1;
arm11->reg_list[i].dirty = 0;
}
/* See e.g. ARM1136 TRM, "14.8.4 Entering Debug state" */ /* See e.g. ARM1136 TRM, "14.8.4 Entering Debug state" */
/* Save DSCR */
R(DSCR) = arm11->dscr;
/* maybe save wDTR (pending DCC write to debug SW, e.g. libdcc) */ /* maybe save wDTR (pending DCC write to debug SW, e.g. libdcc) */
arm11->is_wdtr_saved = !!(arm11->dscr & ARM11_DSCR_WDTR_FULL); arm11->is_wdtr_saved = !!(arm11->dscr & ARM11_DSCR_WDTR_FULL);
if (arm11->is_wdtr_saved) if (arm11->is_wdtr_saved)
@ -336,11 +289,9 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
register_cache_invalidate(arm11->arm.core_cache); register_cache_invalidate(arm11->arm.core_cache);
/* restore DSCR */ /* restore DSCR */
arm11_write_DSCR(arm11, arm11->dscr);
arm11_write_DSCR(arm11, R(DSCR));
/* maybe restore rDTR */ /* maybe restore rDTR */
if (arm11->is_rdtr_saved) if (arm11->is_rdtr_saved)
{ {
arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT); arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
@ -722,9 +673,10 @@ static int arm11_step(struct target *target, int current,
if (arm11_config_step_irq_enable) if (arm11_config_step_irq_enable)
R(DSCR) &= ~ARM11_DSCR_INTERRUPTS_DISABLE; /* should be redundant */ /* this disable should be redundant ... */
arm11->dscr &= ~ARM11_DSCR_INTERRUPTS_DISABLE;
else else
R(DSCR) |= ARM11_DSCR_INTERRUPTS_DISABLE; arm11->dscr |= ARM11_DSCR_INTERRUPTS_DISABLE;
CHECK_RETVAL(arm11_leave_debug_state(arm11, handle_breakpoints)); CHECK_RETVAL(arm11_leave_debug_state(arm11, handle_breakpoints));
@ -769,8 +721,8 @@ static int arm11_step(struct target *target, int current,
/* save state */ /* save state */
CHECK_RETVAL(arm11_debug_entry(arm11)); CHECK_RETVAL(arm11_debug_entry(arm11));
/* restore default state */ /* restore default state */
R(DSCR) &= ~ARM11_DSCR_INTERRUPTS_DISABLE; arm11->dscr &= ~ARM11_DSCR_INTERRUPTS_DISABLE;
} }
@ -1199,12 +1151,7 @@ static int arm11_init_target(struct command_context *cmd_ctx,
struct target *target) struct target *target)
{ {
/* Initialize anything we can set up without talking to the target */ /* Initialize anything we can set up without talking to the target */
return ERROR_OK;
/* REVISIT do we really want such a debug-registers-only cache?
* If we do, it should probably be handled purely by the DPM code,
* so it works identically on the v7a/v7r cores.
*/
return arm11_build_reg_cache(target);
} }
/* talk to the target and set things up */ /* talk to the target and set things up */
@ -1309,117 +1256,6 @@ static int arm11_examine(struct target *target)
} }
/** Load a register that is marked !valid in the register cache */
static int arm11_get_reg(struct reg *reg)
{
struct arm11_reg_state *r = reg->arch_info;
struct target *target = r->target;
if (target->state != TARGET_HALTED)
{
LOG_WARNING("target was not halted");
return ERROR_TARGET_NOT_HALTED;
}
/** \todo TODO: Check this. We assume that all registers are fetched at debug entry. */
#if 0
struct arm11_common *arm11 = target_to_arm11(target);
const struct arm11_reg_defs *arm11_reg_info = arm11_reg_defs + ((struct arm11_reg_state *)reg->arch_info)->def_index;
#endif
return ERROR_OK;
}
/** Change a value in the register cache */
static int arm11_set_reg(struct reg *reg, uint8_t *buf)
{
struct arm11_reg_state *r = reg->arch_info;
struct target *target = r->target;
struct arm11_common *arm11 = target_to_arm11(target);
// const struct arm11_reg_defs *arm11_reg_info = arm11_reg_defs + ((struct arm11_reg_state *)reg->arch_info)->def_index;
arm11->reg_values[((struct arm11_reg_state *)reg->arch_info)->def_index] = buf_get_u32(buf, 0, 32);
reg->valid = 1;
reg->dirty = 1;
return ERROR_OK;
}
static const struct reg_arch_type arm11_reg_type = {
.get = arm11_get_reg,
.set = arm11_set_reg,
};
static int arm11_build_reg_cache(struct target *target)
{
struct arm11_common *arm11 = target_to_arm11(target);
struct reg_cache *cache;
struct reg *reg_list;
struct arm11_reg_state *arm11_reg_states;
cache = calloc(1, sizeof *cache);
reg_list = calloc(ARM11_REGCACHE_COUNT, sizeof *reg_list);
arm11_reg_states = calloc(ARM11_REGCACHE_COUNT,
sizeof *arm11_reg_states);
if (!cache || !reg_list || !arm11_reg_states) {
free(cache);
free(reg_list);
free(arm11_reg_states);
return ERROR_FAIL;
}
arm11->reg_list = reg_list;
/* build cache for some of the debug registers */
cache->name = "arm11 debug registers";
cache->reg_list = reg_list;
cache->num_regs = ARM11_REGCACHE_COUNT;
struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
(*cache_p) = cache;
arm11->core_cache = cache;
size_t i;
/* Not very elegant assertion */
if (ARM11_REGCACHE_COUNT != ARRAY_SIZE(arm11->reg_values) ||
ARM11_REGCACHE_COUNT != ARRAY_SIZE(arm11_reg_defs) ||
ARM11_REGCACHE_COUNT != ARM11_RC_MAX)
{
LOG_ERROR("BUG: arm11->reg_values inconsistent (%d %u %u %d)",
ARM11_REGCACHE_COUNT,
(unsigned) ARRAY_SIZE(arm11->reg_values),
(unsigned) ARRAY_SIZE(arm11_reg_defs),
ARM11_RC_MAX);
/* FIXME minimally, use a build_bug_on(X) mechanism;
* runtime exit() here is bad!
*/
exit(-1);
}
for (i = 0; i < ARM11_REGCACHE_COUNT; i++)
{
struct reg * r = reg_list + i;
const struct arm11_reg_defs * rd = arm11_reg_defs + i;
struct arm11_reg_state * rs = arm11_reg_states + i;
r->name = rd->name;
r->size = 32;
r->value = (uint8_t *)(arm11->reg_values + i);
r->dirty = 0;
r->valid = 0;
r->type = &arm11_reg_type;
r->arch_info = rs;
rs->def_index = i;
rs->target = target;
}
return ERROR_OK;
}
/* FIXME all these BOOL_WRAPPER things should be modifying /* FIXME all these BOOL_WRAPPER things should be modifying
* per-instance state, not shared state; ditto the vector * per-instance state, not shared state; ditto the vector
* catch register support. Scan chains with multiple cores * catch register support. Scan chains with multiple cores

View File

@ -26,8 +26,6 @@
#include "armv4_5.h" #include "armv4_5.h"
#include "arm_dpm.h" #include "arm_dpm.h"
#define ARM11_REGCACHE_COUNT 1
#define ARM11_TAP_DEFAULT TAP_INVALID #define ARM11_TAP_DEFAULT TAP_INVALID
#define CHECK_RETVAL(action) \ #define CHECK_RETVAL(action) \
@ -69,18 +67,6 @@ struct arm11_common
bool simulate_reset_on_next_halt; /**< Perform cleanups of the ARM state on next halt */ bool simulate_reset_on_next_halt; /**< Perform cleanups of the ARM state on next halt */
/** \name Shadow registers to save debug state */
/*@{*/
struct reg * reg_list; /**< target register list */
uint32_t reg_values[ARM11_REGCACHE_COUNT]; /**< data for registers */
/*@}*/
// GA
struct reg_cache *core_cache;
struct arm_jtag jtag_info; struct arm_jtag jtag_info;
}; };