X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Fcortex_a8.c;h=b006e81a64df7f91547fce2a4020b70d2042c083;hb=bf3abc48f008e0a0c0e42b943481872599463af6;hp=01b7aee808b931d8482fe958a1e4a4b0f8877c5b;hpb=d7760352e8044e8eb8cd9b381574e34093e1f26f;p=openocd.git diff --git a/src/target/cortex_a8.c b/src/target/cortex_a8.c index 01b7aee808..b006e81a64 100644 --- a/src/target/cortex_a8.c +++ b/src/target/cortex_a8.c @@ -457,7 +457,7 @@ static int cortex_a8_resume(struct target *target, int current, 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; @@ -496,8 +496,7 @@ static int cortex_a8_resume(struct target *target, int current, /* current = 1: continue on current pc, otherwise continue at
*/ 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; @@ -522,16 +521,13 @@ static int cortex_a8_resume(struct target *target, int current, 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) @@ -587,7 +583,7 @@ static int cortex_a8_debug_entry(struct target *target) 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; @@ -648,41 +644,12 @@ static int cortex_a8_debug_entry(struct target *target) 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; @@ -700,13 +667,10 @@ static int cortex_a8_debug_entry(struct target *target) // 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; @@ -771,7 +735,7 @@ static int cortex_a8_step(struct target *target, int current, uint32_t address, 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; @@ -850,30 +814,84 @@ static int cortex_a8_step(struct target *target, int current, uint32_t address, 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); @@ -889,7 +907,7 @@ static int cortex_a8_load_core_reg_u32(struct target *target, int num, 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)) { @@ -927,7 +945,7 @@ static int cortex_a8_store_core_reg_u32(struct target *target, int num, { 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 @@ -964,16 +982,16 @@ static int cortex_a8_store_core_reg_u32(struct target *target, int num, #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; @@ -988,10 +1006,10 @@ static int cortex_a8_read_core_reg(struct target *target, int 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); } } @@ -1012,24 +1030,23 @@ static int cortex_a8_read_core_reg(struct target *target, int num, 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; @@ -1044,10 +1061,10 @@ static int cortex_a8_write_core_reg(struct target *target, int 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); } } @@ -1068,15 +1085,14 @@ static int cortex_a8_write_core_reg(struct target *target, int num, 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; } @@ -1560,12 +1576,11 @@ static int cortex_a8_examine(struct target *target) 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); }