ARM: define two register utilities
authorDavid Brownell <dbrownell@users.sourceforge.net>
Sun, 22 Nov 2009 11:38:34 +0000 (03:38 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Sun, 22 Nov 2009 11:38:34 +0000 (03:38 -0800)
Define arm_reg_current() ... returning handle to a given register,
and encapsulating the current mode's register shadowing.  It's got
one current use, for reporting the current register set to GDB.
This will let later patches clean up much ARMV4_5_CORE_REG_MODE()
nastiness, saving a bit of code.

Define and use arm_set_cpsr() ... initially it updates the cached
CPSR and sets up state used by arm_reg_current(), plus any SPSR
handle.   (Later: can also set up for T and J bits.)

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/armv4_5.h
src/target/cortex_a8.c
src/target/xscale.c

index 4768f82d77da181fb292e9ff698e6c121ebf1793..ac7e4888832bb9ea3ccceb1f34c8055662ebb4e9 100644 (file)
@@ -347,18 +347,20 @@ static int arm720t_soft_reset_halt(struct target *target)
        target->state = TARGET_HALTED;
 
        /* SVC, ARM state, IRQ and FIQ disabled */
-       buf_set_u32(armv4_5->cpsr->value, 0, 8, 0xd3);
+       uint32_t cpsr;
+
+       cpsr = buf_get_u32(armv4_5->cpsr->value, 0, 32);
+       cpsr &= ~0xff;
+       cpsr |= 0xd3;
+       arm_set_cpsr(armv4_5, cpsr);
        armv4_5->cpsr->dirty = 1;
-       armv4_5->cpsr->valid = 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);
        armv4_5->core_cache->reg_list[15].dirty = 1;
        armv4_5->core_cache->reg_list[15].valid = 1;
 
-       armv4_5->core_mode = ARMV4_5_MODE_SVC;
-       armv4_5->core_state = ARMV4_5_STATE_ARM;
-
        arm720t_disable_mmu_caches(target, 1, 1, 1);
        arm720t->armv4_5_mmu.mmu_enabled = 0;
        arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
index 7ca807a1f297cfa6ba5328d06bd88d7e6e2e60a1..9580f62ee04408413dfd0553f104c0cb0cb8a2f8 100644 (file)
@@ -1227,18 +1227,20 @@ int arm7_9_soft_reset_halt(struct target *target)
        register_cache_invalidate(armv4_5->core_cache);
 
        /* SVC, ARM state, IRQ and FIQ disabled */
-       buf_set_u32(armv4_5->cpsr->value, 0, 8, 0xd3);
+       uint32_t cpsr;
+
+       cpsr = buf_get_u32(armv4_5->cpsr->value, 0, 32);
+       cpsr &= ~0xff;
+       cpsr |= 0xd3;
+       arm_set_cpsr(armv4_5, cpsr);
        armv4_5->cpsr->dirty = 1;
-       armv4_5->cpsr->valid = 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);
        armv4_5->core_cache->reg_list[15].dirty = 1;
        armv4_5->core_cache->reg_list[15].valid = 1;
 
-       armv4_5->core_mode = ARMV4_5_MODE_SVC;
-       armv4_5->core_state = ARMV4_5_STATE_ARM;
-
        /* reset registers */
        for (i = 0; i <= 14; i++)
        {
@@ -1401,11 +1403,7 @@ static int arm7_9_debug_entry(struct target *target)
        if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
                cpsr |= 0x20;
 
-       buf_set_u32(armv4_5->cpsr->value, 0, 32, cpsr);
-       armv4_5->cpsr->dirty = 0;
-       armv4_5->cpsr->valid = 1;
-
-       armv4_5->core_mode = cpsr & 0x1f;
+       arm_set_cpsr(armv4_5, cpsr);
 
        if (!is_arm_mode(armv4_5->core_mode))
        {
index 9cd491f3ea2df09ca68ff7083da2264f89f6edc6..739df3ea3cec396336a0d6e9bdbd0a5f4a576024 100644 (file)
@@ -596,18 +596,20 @@ int arm920t_soft_reset_halt(struct target *target)
        target->state = TARGET_HALTED;
 
        /* SVC, ARM state, IRQ and FIQ disabled */
-       buf_set_u32(armv4_5->cpsr->value, 0, 8, 0xd3);
+       uint32_t cpsr;
+
+       cpsr = buf_get_u32(armv4_5->cpsr->value, 0, 32);
+       cpsr &= ~0xff;
+       cpsr |= 0xd3;
+       arm_set_cpsr(armv4_5, cpsr);
        armv4_5->cpsr->dirty = 1;
-       armv4_5->cpsr->valid = 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);
        armv4_5->core_cache->reg_list[15].dirty = 1;
        armv4_5->core_cache->reg_list[15].valid = 1;
 
-       armv4_5->core_mode = ARMV4_5_MODE_SVC;
-       armv4_5->core_state = ARMV4_5_STATE_ARM;
-
        arm920t_disable_mmu_caches(target, 1, 1, 1);
        arm920t->armv4_5_mmu.mmu_enabled = 0;
        arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
index 44afb2cea352b6754acba54c01bc43d815d1963e..7ecc7824a5ee59267fc0311524c62b712ab5ca08 100644 (file)
@@ -565,18 +565,20 @@ int arm926ejs_soft_reset_halt(struct target *target)
        target->state = TARGET_HALTED;
 
        /* SVC, ARM state, IRQ and FIQ disabled */
-       buf_set_u32(armv4_5->cpsr->value, 0, 8, 0xd3);
+       uint32_t cpsr;
+
+       cpsr = buf_get_u32(armv4_5->cpsr->value, 0, 32);
+       cpsr &= ~0xff;
+       cpsr |= 0xd3;
+       arm_set_cpsr(armv4_5, cpsr);
        armv4_5->cpsr->dirty = 1;
-       armv4_5->cpsr->valid = 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);
        armv4_5->core_cache->reg_list[15].dirty = 1;
        armv4_5->core_cache->reg_list[15].valid = 1;
 
-       armv4_5->core_mode = ARMV4_5_MODE_SVC;
-       armv4_5->core_state = ARMV4_5_STATE_ARM;
-
        arm926ejs_disable_mmu_caches(target, 1, 1, 1);
        arm926ejs->armv4_5_mmu.mmu_enabled = 0;
        arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
index 01d3bc3076cac743b262d43c5953143530094228..3156c666f67a85b321dec9edc1cbc6f31567f42a 100644 (file)
@@ -245,6 +245,10 @@ static const struct {
        unsigned cookie;
        enum armv4_5_mode mode;
 } arm_core_regs[] = {
+       /* IMPORTANT:  we guarantee that the first eight cached registers
+        * correspond to r0..r7, and the fifteenth to PC, so that callers
+        * don't need to map them.
+        */
        { .name = "r0", .cookie = 0, .mode = ARMV4_5_MODE_ANY, },
        { .name = "r1", .cookie = 1, .mode = ARMV4_5_MODE_ANY, },
        { .name = "r2", .cookie = 2, .mode = ARMV4_5_MODE_ANY, },
@@ -255,7 +259,8 @@ static const struct {
        { .name = "r7", .cookie = 7, .mode = ARMV4_5_MODE_ANY, },
 
        /* NOTE: regs 8..12 might be shadowed by FIQ ... flagging
-        * them as MODE_ANY creates special cases.
+        * them as MODE_ANY creates special cases.  (ANY means
+        * "not mapped" elsewhere; here it's "everything but FIQ".)
         */
        { .name = "r8", .cookie = 8, .mode = ARMV4_5_MODE_ANY, },
        { .name = "r9", .cookie = 9, .mode = ARMV4_5_MODE_ANY, },
@@ -267,6 +272,7 @@ static const struct {
        { .name = "sp_usr", .cookie = 13, .mode = ARMV4_5_MODE_USR, },
        { .name = "lr_usr", .cookie = 14, .mode = ARMV4_5_MODE_USR, },
 
+       /* guaranteed to be at index 15 */
        { .name = "pc", .cookie = 15, .mode = ARMV4_5_MODE_ANY, },
 
        { .name = "r8_fiq", .cookie = 8, .mode = ARMV4_5_MODE_FIQ, },
@@ -333,6 +339,73 @@ const int armv4_5_core_reg_map[8][17] =
        }
 };
 
+/**
+ * Configures host-side ARM records to reflect the specified CPSR.
+ * Later, code can use arm_reg_current() to map register numbers
+ * according to how they are exposed by this mode.
+ */
+void arm_set_cpsr(struct arm *arm, uint32_t cpsr)
+{
+       enum armv4_5_mode mode = cpsr & 0x1f;
+       int num;
+
+       /* NOTE:  this may be called very early, before the register
+        * cache is set up.  We can't defend against many errors, in
+        * particular against CPSRs that aren't valid *here* ...
+        */
+       if (arm->cpsr) {
+               buf_set_u32(arm->cpsr->value, 0, 32, cpsr);
+               arm->cpsr->valid = 1;
+               arm->cpsr->dirty = 0;
+       }
+
+       arm->core_mode = mode;
+
+       /* mode_to_number() warned; set up a somewhat-sane mapping */
+       num = armv4_5_mode_to_number(mode);
+       if (num < 0) {
+               mode = ARMV4_5_MODE_USR;
+               num = 0;
+       }
+
+       arm->map = &armv4_5_core_reg_map[num][0];
+       arm->spsr = (mode == ARMV4_5_MODE_USR || mode == ARMV4_5_MODE_SYS)
+                       ? NULL
+                       : arm->core_cache->reg_list + arm->map[16];
+}
+
+/**
+ * Returns handle to the register currently mapped to a given number.
+ * Someone must have called arm_set_cpsr() before.
+ *
+ * \param arm This core's state and registers are used.
+ * \param regnum From 0..15 corresponding to R0..R14 and PC.
+ *     Note that R0..R7 don't require mapping; you may access those
+ *     as the first eight entries in the register cache.  Likewise
+ *     R15 (PC) doesn't need mapping; you may also access it directly.
+ *     However, R8..R14, and SPSR (arm->spsr) *must* be mapped.
+ *     CPSR (arm->cpsr) is also not mapped.
+ */
+struct reg *arm_reg_current(struct arm *arm, unsigned regnum)
+{
+       struct reg *r;
+
+       if (regnum > 16)
+               return NULL;
+
+       r = arm->core_cache->reg_list + arm->map[regnum];
+
+       /* e.g. invalid CPSR said "secure monitor" mode on a core
+        * that doesn't support it...
+        */
+       if (!r) {
+               LOG_ERROR("Invalid CPSR mode");
+               r = arm->core_cache->reg_list + regnum;
+       }
+
+       return r;
+}
+
 static const uint8_t arm_gdb_dummy_fp_value[12];
 
 /**
@@ -446,10 +519,9 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
                {
                        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, reg,
                                        16, ARMV4_5_MODE_ANY, value);
-                       reg->dirty = 0;
+                       arm_set_cpsr(armv4_5_target, value);
                }
        }
 
@@ -752,14 +824,10 @@ int armv4_5_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int
        *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
 
        for (i = 0; i < 16; i++)
-       {
-               (*reg_list)[i] = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i);
-       }
+               (*reg_list)[i] = arm_reg_current(armv4_5, i);
 
        for (i = 16; i < 24; i++)
-       {
                (*reg_list)[i] = &arm_gdb_dummy_fp_reg;
-       }
 
        (*reg_list)[24] = &arm_gdb_dummy_fps_reg;
        (*reg_list)[25] = armv4_5->cpsr;
@@ -805,7 +873,6 @@ int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struc
        struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
        struct armv4_5_algorithm *armv4_5_algorithm_info = arch_info;
        enum armv4_5_state core_state = armv4_5->core_state;
-       enum armv4_5_mode core_mode = armv4_5->core_mode;
        uint32_t context[17];
        uint32_t cpsr;
        int exit_breakpoint_size = 0;
@@ -835,6 +902,9 @@ int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struc
                return ERROR_FAIL;
        }
 
+       /* save r0..pc, cpsr-or-spsr, and then cpsr-for-sure;
+        * they'll be restored later.
+        */
        for (i = 0; i <= 16; i++)
        {
                struct reg *r;
@@ -952,6 +1022,7 @@ int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struc
                }
        }
 
+       /* restore everything we saved before (17 or 18 registers) */
        for (i = 0; i <= 16; i++)
        {
                uint32_t regvalue;
@@ -964,12 +1035,11 @@ int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struc
                        ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1;
                }
        }
-       buf_set_u32(armv4_5->cpsr->value, 0, 32, cpsr);
-       armv4_5->cpsr->valid = 1;
+
+       arm_set_cpsr(armv4_5, cpsr);
        armv4_5->cpsr->dirty = 1;
 
        armv4_5->core_state = core_state;
-       armv4_5->core_mode = core_mode;
 
        return retval;
 }
@@ -1169,8 +1239,8 @@ int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5)
        target->arch_info = 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;
-       armv4_5->core_mode = ARMV4_5_MODE_USR;
 
        /* core_type may be overridden by subtype logic */
        armv4_5->core_type = ARMV4_5_MODE_ANY;
index 5bce30b3b1a5f24b4cb2ab5f553184717b304d31..a9599c82ba97272622e46ce15afd2c71a41b415d 100644 (file)
@@ -85,6 +85,11 @@ struct arm
        /** Handle to the CPSR; valid in all core modes. */
        struct reg *cpsr;
 
+       /** Handle to the SPSR; valid only in core modes with an SPSR. */
+       struct reg *spsr;
+
+       const int *map;
+
        /**
         * Indicates what registers are in the ARM state core register set.
         * ARMV4_5_MODE_ANY indicates the standard set of 37 registers,
@@ -161,6 +166,9 @@ int arm_checksum_memory(struct target *target,
 int arm_blank_check_memory(struct target *target,
                uint32_t address, uint32_t count, uint32_t *blank);
 
+void arm_set_cpsr(struct arm *arm, uint32_t cpsr);
+struct reg *arm_reg_current(struct arm *arm, unsigned regnum);
+
 extern struct reg arm_gdb_dummy_fp_reg;
 extern struct reg arm_gdb_dummy_fps_reg;
 
index 24632099ac47e0aa650e6bcc92ffb3390b904a26..71de3b799267e251a92711ea7482d63b02cea1a6 100644 (file)
@@ -648,7 +648,7 @@ 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;
+       arm_set_cpsr(armv4_5, cpsr);
 
        i = (cpsr >> 5) & 1;    /* T */
        i |= (cpsr >> 23) & 1;  /* J << 1 */
@@ -674,11 +674,6 @@ static int cortex_a8_debug_entry(struct target *target)
        }
 
        /* update cache */
-       reg = 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,
index 3ed7bf0b3bb1f16062dc5867b8090da4b6ac3f9a..659caec18fecf9d6fdd8a6be8884ef62ae413206 100644 (file)
@@ -948,12 +948,9 @@ static int xscale_debug_entry(struct target *target)
                LOG_DEBUG("r%i: 0x%8.8" PRIx32 "", i, buffer[i + 1]);
        }
 
-       buf_set_u32(armv4_5->cpsr->value, 0, 32, buffer[9]);
-       armv4_5->cpsr->dirty = 1;
-       armv4_5->cpsr->valid = 1;
+       arm_set_cpsr(armv4_5, buffer[9]);
        LOG_DEBUG("cpsr: 0x%8.8" PRIx32 "", buffer[9]);
 
-       armv4_5->core_mode = buffer[9] & 0x1f;
        if (!is_arm_mode(armv4_5->core_mode))
        {
                target->state = TARGET_UNKNOWN;

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)