diff options
-rw-r--r-- | src/target/arm720t.c | 1 | ||||
-rw-r--r-- | src/target/arm7_9_common.c | 32 | ||||
-rw-r--r-- | src/target/arm920t.c | 1 | ||||
-rw-r--r-- | src/target/arm926ejs.c | 1 | ||||
-rw-r--r-- | src/target/armv4_5.c | 67 | ||||
-rw-r--r-- | src/target/cortex_a8.c | 23 | ||||
-rw-r--r-- | src/target/xscale.c | 6 |
7 files changed, 52 insertions, 79 deletions
diff --git a/src/target/arm720t.c b/src/target/arm720t.c index ac7e4888..3aa77ea4 100644 --- a/src/target/arm720t.c +++ b/src/target/arm720t.c @@ -354,7 +354,6 @@ static int arm720t_soft_reset_halt(struct target *target) cpsr |= 0xd3; arm_set_cpsr(armv4_5, cpsr); armv4_5->cpsr->dirty = 1; - armv4_5->core_state = ARMV4_5_STATE_ARM; /* start fetching from 0x0 */ buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0); diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index 9580f62e..19fe98d8 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -1223,6 +1223,8 @@ int arm7_9_soft_reset_halt(struct target *target) arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb); } + /* REVISIT likewise for bit 5 -- switch Jazelle-to-ARM */ + /* all register content is now invalid */ register_cache_invalidate(armv4_5->core_cache); @@ -1234,7 +1236,6 @@ int arm7_9_soft_reset_halt(struct target *target) cpsr |= 0xd3; arm_set_cpsr(armv4_5, cpsr); armv4_5->cpsr->dirty = 1; - armv4_5->core_state = ARMV4_5_STATE_ARM; /* start fetching from 0x0 */ buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0); @@ -1334,7 +1335,7 @@ static int arm7_9_debug_entry(struct target *target) uint32_t context[16]; uint32_t* context_p[16]; uint32_t r0_thumb, pc_thumb; - uint32_t cpsr; + uint32_t cpsr, cpsr_mask = 0; int retval; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common; @@ -1379,11 +1380,21 @@ static int arm7_9_debug_entry(struct target *target) LOG_DEBUG("target entered debug from Thumb state"); /* Entered debug from Thumb mode */ armv4_5->core_state = ARMV4_5_STATE_THUMB; + cpsr_mask = 1 << 5; arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb); - LOG_DEBUG("r0_thumb: 0x%8.8" PRIx32 ", pc_thumb: 0x%8.8" PRIx32 "", r0_thumb, pc_thumb); - } - else - { + LOG_DEBUG("r0_thumb: 0x%8.8" PRIx32 + ", pc_thumb: 0x%8.8" PRIx32, r0_thumb, pc_thumb); + } else if (buf_get_u32(dbg_stat->value, 5, 1)) { + /* \todo Get some vaguely correct handling of Jazelle, if + * anyone ever uses it and full info becomes available. + * See ARM9EJS TRM B.7.1 for how to switch J->ARM; and + * B.7.3 for the reverse. That'd be the bare minimum... + */ + LOG_DEBUG("target entered debug from Jazelle state"); + armv4_5->core_state = ARMV4_5_STATE_JAZELLE; + cpsr_mask = 1 << 24; + LOG_ERROR("Jazelle debug entry -- BROKEN!"); + } else { LOG_DEBUG("target entered debug from ARM state"); /* Entered debug from ARM mode */ armv4_5->core_state = ARMV4_5_STATE_ARM; @@ -1399,11 +1410,10 @@ static int arm7_9_debug_entry(struct target *target) if ((retval = jtag_execute_queue()) != ERROR_OK) return retval; - /* if the core has been executing in Thumb state, set the T bit */ - if (armv4_5->core_state == ARMV4_5_STATE_THUMB) - cpsr |= 0x20; - - arm_set_cpsr(armv4_5, cpsr); + /* Sync our CPSR copy with J or T bits EICE reported, but + * which we then erased by putting the core into ARM mode. + */ + arm_set_cpsr(armv4_5, cpsr | cpsr_mask); if (!is_arm_mode(armv4_5->core_mode)) { diff --git a/src/target/arm920t.c b/src/target/arm920t.c index 739df3ea..8a03554f 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -603,7 +603,6 @@ int arm920t_soft_reset_halt(struct target *target) cpsr |= 0xd3; arm_set_cpsr(armv4_5, cpsr); armv4_5->cpsr->dirty = 1; - armv4_5->core_state = ARMV4_5_STATE_ARM; /* start fetching from 0x0 */ buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0); diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c index 7ecc7824..aa299890 100644 --- a/src/target/arm926ejs.c +++ b/src/target/arm926ejs.c @@ -572,7 +572,6 @@ int arm926ejs_soft_reset_halt(struct target *target) cpsr |= 0xd3; arm_set_cpsr(armv4_5, cpsr); armv4_5->cpsr->dirty = 1; - armv4_5->core_state = ARMV4_5_STATE_ARM; /* start fetching from 0x0 */ buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0); diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 3156c666..22e11869 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -372,6 +372,24 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr) arm->spsr = (mode == ARMV4_5_MODE_USR || mode == ARMV4_5_MODE_SYS) ? NULL : arm->core_cache->reg_list + arm->map[16]; + + /* Older ARMs won't have the J bit */ + enum armv4_5_state state; + + if (cpsr & (1 << 5)) { /* T */ + if (cpsr & (1 << 24)) { /* J */ + LOG_WARNING("ThumbEE -- incomplete support"); + state = ARM_STATE_THUMB_EE; + } else + state = ARMV4_5_STATE_THUMB; + } else { + if (cpsr & (1 << 24)) { /* J */ + LOG_ERROR("Jazelle state handling is BROKEN!"); + state = ARMV4_5_STATE_JAZELLE; + } else + state = ARMV4_5_STATE_ARM; + } + arm->core_state = state; } /** @@ -481,49 +499,27 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf) /* 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->cpsr) { + arm_set_cpsr(armv4_5_target, value); - if (reg == armv4_5_target->cpsr) - { - /* FIXME handle J bit too; mostly for ThumbEE, also Jazelle */ - if (value & 0x20) - { - /* T bit should be set */ - if (armv4_5_target->core_state == ARMV4_5_STATE_ARM) - { - /* change state to Thumb */ - LOG_DEBUG("changing to Thumb state"); - armv4_5_target->core_state = ARMV4_5_STATE_THUMB; - } - } - else - { - /* T bit should be cleared */ - if (armv4_5_target->core_state == ARMV4_5_STATE_THUMB) - { - /* change state to ARM */ - LOG_DEBUG("changing to ARM state"); - armv4_5_target->core_state = ARMV4_5_STATE_ARM; - } - } - - /* 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... + /* Older cores need help to be in ARM mode during halt + * mode debug, so we clear the J and T bits if we flush. + * For newer cores (v6/v7a/v7r) we don't need that, but + * it won't hurt since CPSR is always flushed anyway. */ - - if (armv4_5_target->core_mode != (enum armv4_5_mode)(value & 0x1f)) - { + 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)); + value &= ~((1 << 24) | (1 << 5)); armv4_5_target->write_core_reg(target, reg, 16, ARMV4_5_MODE_ANY, value); - arm_set_cpsr(armv4_5_target, value); } + } else { + buf_set_u32(reg->value, 0, 32, value); + reg->valid = 1; } + reg->dirty = 1; return ERROR_OK; } @@ -1240,7 +1236,6 @@ int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5) armv4_5->common_magic = ARMV4_5_COMMON_MAGIC; arm_set_cpsr(armv4_5, ARMV4_5_MODE_USR); - armv4_5->core_state = ARMV4_5_STATE_ARM; /* core_type may be overridden by subtype logic */ armv4_5->core_type = ARMV4_5_MODE_ANY; diff --git a/src/target/cortex_a8.c b/src/target/cortex_a8.c index 71de3b79..fa26b6ab 100644 --- a/src/target/cortex_a8.c +++ b/src/target/cortex_a8.c @@ -650,29 +650,6 @@ static int cortex_a8_debug_entry(struct target *target) arm_set_cpsr(armv4_5, cpsr); - 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; - } - /* update cache */ for (i = 0; i <= ARM_PC; i++) { diff --git a/src/target/xscale.c b/src/target/xscale.c index 659caec1..e8a3e49f 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -960,12 +960,6 @@ static int xscale_debug_entry(struct target *target) LOG_DEBUG("target entered debug state in %s mode", arm_mode_name(armv4_5->core_mode)); - if (buffer[9] & 0x20) - armv4_5->core_state = ARMV4_5_STATE_THUMB; - else - armv4_5->core_state = ARMV4_5_STATE_ARM; - - /* get banked registers, r8 to r14, and spsr if not in USR/SYS mode */ if ((armv4_5->core_mode != ARMV4_5_MODE_USR) && (armv4_5->core_mode != ARMV4_5_MODE_SYS)) { |