uint32_t address, int handle_breakpoints, int debug_execution)
{
struct armv7a_common *armv7a = target_to_armv7a(target);
- struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
+ struct arm *armv4_5 = &armv7a->armv4_5_common;
struct swjdp_common *swjdp = &armv7a->swjdp_info;
// struct breakpoint *breakpoint = NULL;
/* current = 1: continue on current pc, otherwise continue at <address> */
resume_pc = buf_get_u32(
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
- armv4_5->core_mode, 15).value,
+ armv4_5->core_cache->reg_list[15].value,
0, 32);
if (!current)
resume_pc = address;
return ERROR_FAIL;
}
LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc);
- buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
- armv4_5->core_mode, 15).value,
+ buf_set_u32(armv4_5->core_cache->reg_list[15].value,
0, 32, resume_pc);
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
- armv4_5->core_mode, 15).dirty = 1;
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
- armv4_5->core_mode, 15).valid = 1;
+ armv4_5->core_cache->reg_list[15].dirty = 1;
+ armv4_5->core_cache->reg_list[15].valid = 1;
cortex_a8_restore_context(target);
-// arm7_9_restore_context(target); TODO Context is currently NOT Properly restored
+
#if 0
/* the front-end may request us not to handle breakpoints */
if (handle_breakpoints)
struct working_area *regfile_working_area = NULL;
struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
struct armv7a_common *armv7a = target_to_armv7a(target);
- struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
+ struct arm *armv4_5 = &armv7a->armv4_5_common;
struct swjdp_common *swjdp = &armv7a->swjdp_info;
struct reg *reg;
dap_ap_select(swjdp, swjdp_debugap);
LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr);
- armv4_5->core_mode = cpsr & 0x1F;
-
- i = (cpsr >> 5) & 1; /* T */
- i |= (cpsr >> 23) & 1; /* J << 1 */
- switch (i) {
- case 0: /* J = 0, T = 0 */
- armv4_5->core_state = ARMV4_5_STATE_ARM;
- break;
- case 1: /* J = 0, T = 1 */
- armv4_5->core_state = ARMV4_5_STATE_THUMB;
- break;
- case 2: /* J = 1, T = 0 */
- LOG_WARNING("Jazelle state -- not handled");
- armv4_5->core_state = ARMV4_5_STATE_JAZELLE;
- break;
- case 3: /* J = 1, T = 1 */
- /* ThumbEE is very much like Thumb, but some of the
- * instructions are different. Single stepping and
- * breakpoints need updating...
- */
- LOG_WARNING("ThumbEE -- incomplete support");
- armv4_5->core_state = ARM_STATE_THUMB_EE;
- break;
- }
+ arm_set_cpsr(armv4_5, cpsr);
/* update cache */
- reg = armv4_5->core_cache->reg_list + ARMV4_5_CPSR;
- buf_set_u32(reg->value, 0, 32, cpsr);
- reg->valid = 1;
- reg->dirty = 0;
-
for (i = 0; i <= ARM_PC; i++)
{
- reg = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
- armv4_5->core_mode, i);
+ reg = arm_reg_current(armv4_5, i);
buf_set_u32(reg->value, 0, 32, regfile[i]);
reg->valid = 1;
// ARM state
regfile[ARM_PC] -= 8;
}
- buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
- armv4_5->core_mode, ARM_PC).value,
- 0, 32, regfile[ARM_PC]);
- ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0)
- .dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
- armv4_5->core_mode, 0).valid;
+ reg = armv4_5->core_cache->reg_list + 15;
+ buf_set_u32(reg->value, 0, 32, regfile[ARM_PC]);
+ reg->dirty = reg->valid;
ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 15)
.dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
armv4_5->core_mode, 15).valid;
int handle_breakpoints)
{
struct armv7a_common *armv7a = target_to_armv7a(target);
- struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
+ struct arm *armv4_5 = &armv7a->armv4_5_common;
struct breakpoint *breakpoint = NULL;
struct breakpoint stepbreakpoint;
static int cortex_a8_restore_context(struct target *target)
{
- int i;
uint32_t value;
struct armv7a_common *armv7a = target_to_armv7a(target);
- struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
+ struct reg_cache *cache = armv7a->armv4_5_common.core_cache;
+ unsigned max = cache->num_regs;
+ struct reg *r;
+ bool flushed, flush_cpsr = false;
LOG_DEBUG(" ");
if (armv7a->pre_restore_context)
armv7a->pre_restore_context(target);
- for (i = 15; i >= 0; i--)
- {
- if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
- armv4_5->core_mode, i).dirty)
- {
- value = buf_get_u32(ARMV4_5_CORE_REG_MODE(
- armv4_5->core_cache,
- armv4_5->core_mode, i).value,
- 0, 32);
+ /* Flush all dirty registers from the cache, one mode at a time so
+ * that we write CPSR as little as possible. Save CPSR and R0 for
+ * last; they're used to change modes and write other registers.
+ *
+ * REVISIT be smarter: save eventual mode for last loop, don't
+ * need to write CPSR an extra time.
+ */
+ do {
+ enum armv4_5_mode mode = ARMV4_5_MODE_ANY;
+ unsigned i;
+
+ flushed = false;
+
+ /* write dirty non-{R0,CPSR} registers sharing the same mode */
+ for (i = max - 1, r = cache->reg_list + 1; i > 0; i--, r++) {
+ struct arm_reg *reg;
+
+ if (!r->dirty || r == armv7a->armv4_5_common.cpsr)
+ continue;
+ reg = r->arch_info;
+
/* TODO Check return values */
- cortex_a8_dap_write_coreregister_u32(target, value, i);
+
+ /* Pick a mode and update CPSR; else ignore this
+ * register if it's for a different mode than what
+ * we're handling on this pass.
+ *
+ * REVISIT don't distinguish SYS and USR modes.
+ *
+ * FIXME if we restore from FIQ mode, R8..R12 will
+ * get wrongly flushed onto FIQ shadows...
+ */
+ if (mode == ARMV4_5_MODE_ANY) {
+ mode = reg->mode;
+ if (mode != ARMV4_5_MODE_ANY) {
+ cortex_a8_dap_write_coreregister_u32(
+ target, mode, 16);
+ flush_cpsr = true;
+ }
+ } else if (mode != reg->mode)
+ continue;
+
+ /* Write this register */
+ value = buf_get_u32(r->value, 0, 32);
+ cortex_a8_dap_write_coreregister_u32(target, value,
+ (reg->num == 16) ? 17 : reg->num);
+ r->dirty = false;
+ flushed = true;
}
+
+ } while (flushed);
+
+ /* now flush CPSR if needed ... */
+ r = armv7a->armv4_5_common.cpsr;
+ if (flush_cpsr || r->dirty) {
+ value = buf_get_u32(r->value, 0, 32);
+ cortex_a8_dap_write_coreregister_u32(target, value, 16);
+ r->dirty = false;
}
+ /* ... and R0 always (it was dirtied when we saved context) */
+ r = cache->reg_list + 0;
+ value = buf_get_u32(r->value, 0, 32);
+ cortex_a8_dap_write_coreregister_u32(target, value, 0);
+ r->dirty = false;
+
if (armv7a->post_restore_context)
armv7a->post_restore_context(target);
armv4_5_mode_t mode, uint32_t * value)
{
int retval;
- struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
+ struct arm *armv4_5 = target_to_armv4_5(target);
if ((num <= ARM_CPSR))
{
{
int retval;
// uint32_t reg;
- struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
+ struct arm *armv4_5 = target_to_armv4_5(target);
#ifdef ARMV7_GDB_HACKS
/* If the LR register is being modified, make sure it will put us
#endif
-static int cortex_a8_write_core_reg(struct target *target, int num,
- enum armv4_5_mode mode, uint32_t value);
+static int cortex_a8_write_core_reg(struct target *target, struct reg *r,
+ int num, enum armv4_5_mode mode, uint32_t value);
-static int cortex_a8_read_core_reg(struct target *target, int num,
- enum armv4_5_mode mode)
+static int cortex_a8_read_core_reg(struct target *target, struct reg *r,
+ int num, enum armv4_5_mode mode)
{
uint32_t value;
int retval;
- struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
- struct reg_cache *cache = armv4_5->core_cache;
+ struct arm *armv4_5 = target_to_armv4_5(target);
+ struct reg *cpsr_r = NULL;
uint32_t cpsr = 0;
unsigned cookie = num;
mode = ARMV4_5_MODE_ANY;
if (mode != ARMV4_5_MODE_ANY) {
- cpsr = buf_get_u32(cache ->reg_list[ARMV4_5_CPSR]
- .value, 0, 32);
- cortex_a8_write_core_reg(target, 16,
- ARMV4_5_MODE_ANY, mode);
+ cpsr_r = armv4_5->cpsr;
+ cpsr = buf_get_u32(cpsr_r->value, 0, 32);
+ cortex_a8_write_core_reg(target, cpsr_r,
+ 16, ARMV4_5_MODE_ANY, mode);
}
}
cortex_a8_dap_read_coreregister_u32(target, &value, cookie);
retval = jtag_execute_queue();
if (retval == ERROR_OK) {
- struct reg *r = &ARMV4_5_CORE_REG_MODE(cache, mode, num);
-
r->valid = 1;
r->dirty = 0;
buf_set_u32(r->value, 0, 32, value);
}
- if (cpsr)
- cortex_a8_write_core_reg(target, 16, ARMV4_5_MODE_ANY, cpsr);
+ if (cpsr_r)
+ cortex_a8_write_core_reg(target, cpsr_r,
+ 16, ARMV4_5_MODE_ANY, cpsr);
return retval;
}
-static int cortex_a8_write_core_reg(struct target *target, int num,
- enum armv4_5_mode mode, uint32_t value)
+static int cortex_a8_write_core_reg(struct target *target, struct reg *r,
+ int num, enum armv4_5_mode mode, uint32_t value)
{
int retval;
- struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
- struct reg_cache *cache = armv4_5->core_cache;
+ struct arm *armv4_5 = target_to_armv4_5(target);
+ struct reg *cpsr_r = NULL;
uint32_t cpsr = 0;
unsigned cookie = num;
mode = ARMV4_5_MODE_ANY;
if (mode != ARMV4_5_MODE_ANY) {
- cpsr = buf_get_u32(cache ->reg_list[ARMV4_5_CPSR]
- .value, 0, 32);
- cortex_a8_write_core_reg(target, 16,
- ARMV4_5_MODE_ANY, mode);
+ cpsr_r = armv4_5->cpsr;
+ cpsr = buf_get_u32(cpsr_r->value, 0, 32);
+ cortex_a8_write_core_reg(target, cpsr_r,
+ 16, ARMV4_5_MODE_ANY, mode);
}
}
cortex_a8_dap_write_coreregister_u32(target, value, cookie);
if ((retval = jtag_execute_queue()) == ERROR_OK) {
- struct reg *r = &ARMV4_5_CORE_REG_MODE(cache, mode, num);
-
buf_set_u32(r->value, 0, 32, value);
r->valid = 1;
r->dirty = 0;
}
- if (cpsr)
- cortex_a8_write_core_reg(target, 16, ARMV4_5_MODE_ANY, cpsr);
+ if (cpsr_r)
+ cortex_a8_write_core_reg(target, cpsr_r,
+ 16, ARMV4_5_MODE_ANY, cpsr);
return retval;
}
static void cortex_a8_build_reg_cache(struct target *target)
{
struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
- struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
+ struct arm *armv4_5 = target_to_armv4_5(target);
armv4_5->core_type = ARM_MODE_MON;
(*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
- armv4_5->core_cache = (*cache_p);
}