summaryrefslogtreecommitdiff
path: root/src/target/armv4_5.c
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-11-20 16:27:24 -0800
committerDavid Brownell <dbrownell@users.sourceforge.net>2009-11-20 16:27:24 -0800
commit69c751956293e822faa6cf844f2864d81c36a578 (patch)
tree5a13deb8230c7a3436e53e9618e27ab6421a08e4 /src/target/armv4_5.c
parent85fe1506a2296493d13368e545fa2d4ddb13ea72 (diff)
downloadopenocd+libswd-69c751956293e822faa6cf844f2864d81c36a578.tar.gz
openocd+libswd-69c751956293e822faa6cf844f2864d81c36a578.tar.bz2
openocd+libswd-69c751956293e822faa6cf844f2864d81c36a578.tar.xz
openocd+libswd-69c751956293e822faa6cf844f2864d81c36a578.zip
ARM: pass 'struct reg *' to register r/w routines
Implementations need to access the register struct they modify; make it easier and less error-prone to identify the instance. (This removes over 10% of the ARMV4_5_CORE_REG_MODE nastiness...) Plus some minor fixes noted when making these updates: ARM7/ARM9 accessor methods should be static; don't leave CPSR wrongly marked "dirty"; note significant XScale omissions in register handling; and have armv4_5_build_reg_cache() record its result. Rename "struct armv4_5_core_reg" as "struct arm_reg"; it's used for more than those older architecture generations. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Diffstat (limited to 'src/target/armv4_5.c')
-rw-r--r--src/target/armv4_5.c47
1 files changed, 33 insertions, 14 deletions
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
index f8ab1532..71c7299e 100644
--- a/src/target/armv4_5.c
+++ b/src/target/armv4_5.c
@@ -363,7 +363,7 @@ static void arm_gdb_dummy_init(void)
static int armv4_5_get_core_reg(struct reg *reg)
{
int retval;
- struct armv4_5_core_reg *armv4_5 = reg->arch_info;
+ struct arm_reg *armv4_5 = reg->arch_info;
struct target *target = armv4_5->target;
if (target->state != TARGET_HALTED)
@@ -372,16 +372,18 @@ static int armv4_5_get_core_reg(struct reg *reg)
return ERROR_TARGET_NOT_HALTED;
}
- retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
- if (retval == ERROR_OK)
+ retval = armv4_5->armv4_5_common->read_core_reg(target, reg, armv4_5->num, armv4_5->mode);
+ if (retval == ERROR_OK) {
reg->valid = 1;
+ reg->dirty = 0;
+ }
return retval;
}
static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
{
- struct armv4_5_core_reg *armv4_5 = reg->arch_info;
+ struct arm_reg *armv4_5 = reg->arch_info;
struct target *target = armv4_5->target;
struct armv4_5_common_s *armv4_5_target = target_to_armv4_5(target);
uint32_t value = buf_get_u32(buf, 0, 32);
@@ -392,8 +394,16 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
return ERROR_TARGET_NOT_HALTED;
}
+ /* Except for CPSR, the "reg" command exposes a writeback model
+ * for the register cache.
+ */
+ buf_set_u32(reg->value, 0, 32, value);
+ reg->dirty = 1;
+ reg->valid = 1;
+
if (reg == &armv4_5_target->core_cache->reg_list[ARMV4_5_CPSR])
{
+ /* FIXME handle J bit too; mostly for ThumbEE, also Jazelle */
if (value & 0x20)
{
/* T bit should be set */
@@ -415,19 +425,23 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
}
}
+ /* REVISIT Why only update core for mode change, not also
+ * for state changes? Possibly older cores need to stay
+ * in ARM mode during halt mode debug, not execute Thumb;
+ * v6/v7a/v7r seem to do that automatically...
+ */
+
if (armv4_5_target->core_mode != (enum armv4_5_mode)(value & 0x1f))
{
LOG_DEBUG("changing ARM core mode to '%s'",
arm_mode_name(value & 0x1f));
armv4_5_target->core_mode = value & 0x1f;
- armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value);
+ armv4_5_target->write_core_reg(target, reg,
+ 16, ARMV4_5_MODE_ANY, value);
+ reg->dirty = 0;
}
}
- buf_set_u32(reg->value, 0, 32, value);
- reg->dirty = 1;
- reg->valid = 1;
-
return ERROR_OK;
}
@@ -441,8 +455,7 @@ struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *arm
int num_regs = ARRAY_SIZE(arm_core_regs);
struct reg_cache *cache = malloc(sizeof(struct reg_cache));
struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
- struct armv4_5_core_reg *arch_info = calloc(num_regs,
- sizeof(struct armv4_5_core_reg));
+ struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
int i;
if (!cache || !reg_list || !arch_info) {
@@ -480,6 +493,7 @@ struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *arm
cache->num_regs++;
}
+ armv4_5_common->core_cache = cache;
return cache;
}
@@ -811,9 +825,14 @@ int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struc
for (i = 0; i <= 16; i++)
{
- if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
- armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
- context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
+ struct reg *r;
+
+ r = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+ armv4_5_algorithm_info->core_mode, i);
+ if (!r->valid)
+ armv4_5->read_core_reg(target, r, i,
+ armv4_5_algorithm_info->core_mode);
+ context[i] = buf_get_u32(r->value, 0, 32);
}
cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);