]> git.sur5r.net Git - openocd/commitdiff
ARM: arm_set_cpsr() handles T and J bits
authorDavid Brownell <dbrownell@users.sourceforge.net>
Sun, 22 Nov 2009 11:41:14 +0000 (03:41 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Sun, 22 Nov 2009 11:41:14 +0000 (03:41 -0800)
Have arm_set_cpsr() handle the two core state flags, updating
the CPU state.  This eliminates code in various debug_entry()
paths, and marginally improves handling of the J bit.

Catch and comment a few holes in the handling of the J bit on
ARM926ejs cores ... it's unlikely our users will care about
Jazelle mode, but we can at least warn of Impending Doom.  If
anyone does use it, these breadcrumbs may help them to find
the right path through the code.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
src/target/arm720t.c
src/target/arm7_9_common.c
src/target/arm920t.c
src/target/arm926ejs.c
src/target/armv4_5.c
src/target/cortex_a8.c
src/target/xscale.c

index ac7e4888832bb9ea3ccceb1f34c8055662ebb4e9..3aa77ea4ef7832d6a280dee38682c1c77f38257a 100644 (file)
@@ -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);
index 9580f62ee04408413dfd0553f104c0cb0cb8a2f8..19fe98d8d8a2747f4d0dab15be60f88c5c791440 100644 (file)
@@ -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))
        {
index 739df3ea3cec396336a0d6e9bdbd0a5f4a576024..8a03554f62cb175c8082852c784438b145c3865c 100644 (file)
@@ -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);
index 7ecc7824a5ee59267fc0311524c62b712ab5ca08..aa2998905590aab453b14903389fa1c0e45ee00b 100644 (file)
@@ -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);
index 3156c666f67a85b321dec9edc1cbc6f31567f42a..22e11869ff5449c8f9e7099fe84eb6ab56f3914a 100644 (file)
@@ -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;
index 71de3b799267e251a92711ea7482d63b02cea1a6..fa26b6ab0d453ec5ca58ab72d992afaaadaaa6ca 100644 (file)
@@ -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++)
        {
index 659caec18fecf9d6fdd8a6be8884ef62ae413206..e8a3e49fd0a0377cf9d1e439d3eefa9cfcd2e20c 100644 (file)
@@ -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))
        {