ARM: pass 'struct reg *' to register r/w routines
authorDavid Brownell <dbrownell@users.sourceforge.net>
Sat, 21 Nov 2009 00:27:24 +0000 (16:27 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Sat, 21 Nov 2009 00:27:24 +0000 (16:27 -0800)
Implementations need to access the register struct they modify;
make it easier and less error-prone to identify the instance.
(This removes over 10% of the ARMV4_5_CORE_REG_MODE nastiness...)

Plus some minor fixes noted when making these updates:  ARM7/ARM9
accessor methods should be static; don't leave CPSR wrongly marked
"dirty"; note significant XScale omissions in register handling;
and have armv4_5_build_reg_cache() record its result.

Rename "struct armv4_5_core_reg" as "struct arm_reg"; it's used
for more than those older architecture generations.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
src/target/arm7_9_common.c
src/target/arm7_9_common.h
src/target/arm7tdmi.c
src/target/arm9tdmi.c
src/target/armv4_5.c
src/target/armv4_5.h
src/target/cortex_a8.c
src/target/xscale.c

index 7a2b54294c3b206a91a9ee9cc4f12a6b5f528119..3a32764662ad2b35d63f7a4ef317b7a7ac2d26ff 100644 (file)
@@ -1577,7 +1577,7 @@ int arm7_9_restore_context(struct target *target)
        struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
        struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
        struct reg *reg;
-       struct armv4_5_core_reg *reg_arch_info;
+       struct arm_reg *reg_arch_info;
        enum armv4_5_mode current_mode = armv4_5->core_mode;
        int i, j;
        int dirty;
@@ -2084,25 +2084,24 @@ int arm7_9_step(struct target *target, int current, uint32_t address, int handle
        return err;
 }
 
-int arm7_9_read_core_reg(struct target *target, int num, enum armv4_5_mode mode)
+static int arm7_9_read_core_reg(struct target *target, struct reg *r,
+               int num, enum armv4_5_mode mode)
 {
        uint32_t* reg_p[16];
        uint32_t value;
        int retval;
+       struct arm_reg *areg = r->arch_info;
        struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
        struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
 
        if (!is_arm_mode(armv4_5->core_mode))
                return ERROR_FAIL;
-
-       enum armv4_5_mode reg_mode = ((struct armv4_5_core_reg*)ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).arch_info)->mode;
-
        if ((num < 0) || (num > 16))
                return ERROR_INVALID_ARGUMENTS;
 
        if ((mode != ARMV4_5_MODE_ANY)
                        && (mode != armv4_5->core_mode)
-                       && (reg_mode != ARMV4_5_MODE_ANY))
+                       && (areg->mode != ARMV4_5_MODE_ANY))
        {
                uint32_t tmp_cpsr;
 
@@ -2125,10 +2124,7 @@ int arm7_9_read_core_reg(struct target *target, int num, enum armv4_5_mode mode)
                /* read a program status register
                 * if the register mode is MODE_ANY, we read the cpsr, otherwise a spsr
                 */
-               struct armv4_5_core_reg *arch_info = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).arch_info;
-               int spsr = (arch_info->mode == ARMV4_5_MODE_ANY) ? 0 : 1;
-
-               arm7_9->read_xpsr(target, &value, spsr);
+               arm7_9->read_xpsr(target, &value, areg->mode != ARMV4_5_MODE_ANY);
        }
 
        if ((retval = jtag_execute_queue()) != ERROR_OK)
@@ -2136,13 +2132,13 @@ int arm7_9_read_core_reg(struct target *target, int num, enum armv4_5_mode mode)
                return retval;
        }
 
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).valid = 1;
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).dirty = 0;
-       buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).value, 0, 32, value);
+       r->valid = 1;
+       r->dirty = 0;
+       buf_set_u32(r->value, 0, 32, value);
 
        if ((mode != ARMV4_5_MODE_ANY)
                        && (mode != armv4_5->core_mode)
-                       && (reg_mode != ARMV4_5_MODE_ANY))      {
+                       && (areg->mode != ARMV4_5_MODE_ANY))    {
                /* restore processor mode (mask T bit) */
                arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
        }
@@ -2150,23 +2146,22 @@ int arm7_9_read_core_reg(struct target *target, int num, enum armv4_5_mode mode)
        return ERROR_OK;
 }
 
-int arm7_9_write_core_reg(struct target *target, int num, enum armv4_5_mode mode, uint32_t value)
+static int arm7_9_write_core_reg(struct target *target, struct reg *r,
+               int num, enum armv4_5_mode mode, uint32_t value)
 {
        uint32_t reg[16];
+       struct arm_reg *areg = r->arch_info;
        struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
        struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
 
        if (!is_arm_mode(armv4_5->core_mode))
                return ERROR_FAIL;
-
-       enum armv4_5_mode reg_mode = ((struct armv4_5_core_reg*)ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).arch_info)->mode;
-
        if ((num < 0) || (num > 16))
                return ERROR_INVALID_ARGUMENTS;
 
        if ((mode != ARMV4_5_MODE_ANY)
                        && (mode != armv4_5->core_mode)
-                       && (reg_mode != ARMV4_5_MODE_ANY))      {
+                       && (areg->mode != ARMV4_5_MODE_ANY))    {
                uint32_t tmp_cpsr;
 
                /* change processor mode (mask T bit) */
@@ -2188,8 +2183,7 @@ int arm7_9_write_core_reg(struct target *target, int num, enum armv4_5_mode mode
                /* write a program status register
                * if the register mode is MODE_ANY, we write the cpsr, otherwise a spsr
                */
-               struct armv4_5_core_reg *arch_info = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).arch_info;
-               int spsr = (arch_info->mode == ARMV4_5_MODE_ANY) ? 0 : 1;
+               int spsr = (areg->mode != ARMV4_5_MODE_ANY);
 
                /* if we're writing the CPSR, mask the T bit */
                if (!spsr)
@@ -2198,12 +2192,12 @@ int arm7_9_write_core_reg(struct target *target, int num, enum armv4_5_mode mode
                arm7_9->write_xpsr(target, value, spsr);
        }
 
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).valid = 1;
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, num).dirty = 0;
+       r->valid = 1;
+       r->dirty = 0;
 
        if ((mode != ARMV4_5_MODE_ANY)
                        && (mode != armv4_5->core_mode)
-                       && (reg_mode != ARMV4_5_MODE_ANY))      {
+                       && (areg->mode != ARMV4_5_MODE_ANY))    {
                /* restore processor mode (mask T bit) */
                arm7_9->write_xpsr_im8(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8) & ~0x20, 0, 0);
        }
index 266bf800234a3bce150252770ff9761b89c34567..2f7132a15bb1a1e6dbf03726f4f551bbb5084967 100644 (file)
@@ -139,7 +139,6 @@ int arm7_9_full_context(struct target *target);
 int arm7_9_restore_context(struct target *target);
 int arm7_9_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution);
 int arm7_9_step(struct target *target, int current, uint32_t address, int handle_breakpoints);
-int arm7_9_read_core_reg(struct target *target, int num, enum armv4_5_mode mode);
 int arm7_9_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
 int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
 int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer);
index 3bd5236442210313a7591df03bdbdb8db381a959..e7ea768f988c4a1dd22a113ab254c5d02fce17ea 100644 (file)
@@ -644,7 +644,6 @@ static void arm7tdmi_build_reg_cache(struct target *target)
        struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
 
        (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
-       armv4_5->core_cache = (*cache_p);
 }
 
 int arm7tdmi_init_target(struct command_context *cmd_ctx, struct target *target)
index a69e49e74b2c105058d90b5489f14e5ff7b92fe5..38b2284b680beb61c64286ac805573671bb188f8 100644 (file)
@@ -754,7 +754,6 @@ static void arm9tdmi_build_reg_cache(struct target *target)
        struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
 
        (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
-       armv4_5->core_cache = (*cache_p);
 }
 
 int arm9tdmi_init_target(struct command_context *cmd_ctx,
index f8ab15322a56d0b0a86c4602007aa90a6b9725a4..71c7299e736cb34a18747f40530fed546db1fcfd 100644 (file)
@@ -363,7 +363,7 @@ static void arm_gdb_dummy_init(void)
 static int armv4_5_get_core_reg(struct reg *reg)
 {
        int retval;
-       struct armv4_5_core_reg *armv4_5 = reg->arch_info;
+       struct arm_reg *armv4_5 = reg->arch_info;
        struct target *target = armv4_5->target;
 
        if (target->state != TARGET_HALTED)
@@ -372,16 +372,18 @@ static int armv4_5_get_core_reg(struct reg *reg)
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       retval = armv4_5->armv4_5_common->read_core_reg(target, armv4_5->num, armv4_5->mode);
-       if (retval == ERROR_OK)
+       retval = armv4_5->armv4_5_common->read_core_reg(target, reg, armv4_5->num, armv4_5->mode);
+       if (retval == ERROR_OK) {
                reg->valid = 1;
+               reg->dirty = 0;
+       }
 
        return retval;
 }
 
 static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
 {
-       struct armv4_5_core_reg *armv4_5 = reg->arch_info;
+       struct arm_reg *armv4_5 = reg->arch_info;
        struct target *target = armv4_5->target;
        struct armv4_5_common_s *armv4_5_target = target_to_armv4_5(target);
        uint32_t value = buf_get_u32(buf, 0, 32);
@@ -392,8 +394,16 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
                return ERROR_TARGET_NOT_HALTED;
        }
 
+       /* 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->core_cache->reg_list[ARMV4_5_CPSR])
        {
+               /* FIXME handle J bit too; mostly for ThumbEE, also Jazelle */
                if (value & 0x20)
                {
                        /* T bit should be set */
@@ -415,19 +425,23 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
                        }
                }
 
+               /* 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...
+                */
+
                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));
                        armv4_5_target->core_mode = value & 0x1f;
-                       armv4_5_target->write_core_reg(target, 16, ARMV4_5_MODE_ANY, value);
+                       armv4_5_target->write_core_reg(target, reg,
+                                       16, ARMV4_5_MODE_ANY, value);
+                       reg->dirty = 0;
                }
        }
 
-       buf_set_u32(reg->value, 0, 32, value);
-       reg->dirty = 1;
-       reg->valid = 1;
-
        return ERROR_OK;
 }
 
@@ -441,8 +455,7 @@ struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *arm
        int num_regs = ARRAY_SIZE(arm_core_regs);
        struct reg_cache *cache = malloc(sizeof(struct reg_cache));
        struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
-       struct armv4_5_core_reg *arch_info = calloc(num_regs,
-                                       sizeof(struct armv4_5_core_reg));
+       struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
        int i;
 
        if (!cache || !reg_list || !arch_info) {
@@ -480,6 +493,7 @@ struct reg_cache* armv4_5_build_reg_cache(struct target *target, struct arm *arm
                cache->num_regs++;
        }
 
+       armv4_5_common->core_cache = cache;
        return cache;
 }
 
@@ -811,9 +825,14 @@ int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struc
 
        for (i = 0; i <= 16; i++)
        {
-               if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid)
-                       armv4_5->read_core_reg(target, i, armv4_5_algorithm_info->core_mode);
-               context[i] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32);
+               struct reg *r;
+
+               r = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+                               armv4_5_algorithm_info->core_mode, i);
+               if (!r->valid)
+                       armv4_5->read_core_reg(target, r, i,
+                                       armv4_5_algorithm_info->core_mode);
+               context[i] = buf_get_u32(r->value, 0, 32);
        }
        cpsr = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32);
 
index dbd62c0d7fee9b7a288ae9bcef40df6ece7d04a0..c8fc558082fe502e7cdaefc7683786284d66878a 100644 (file)
@@ -109,9 +109,9 @@ struct arm
        struct etm_context *etm;
 
        int (*full_context)(struct target *target);
-       int (*read_core_reg)(struct target *target,
+       int (*read_core_reg)(struct target *target, struct reg *reg,
                        int num, enum armv4_5_mode mode);
-       int (*write_core_reg)(struct target *target,
+       int (*write_core_reg)(struct target *target, struct reg *reg,
                        int num, enum armv4_5_mode mode, uint32_t value);
        void *arch_info;
 };
@@ -137,7 +137,7 @@ struct armv4_5_algorithm
        enum armv4_5_state core_state;
 };
 
-struct armv4_5_core_reg
+struct arm_reg
 {
        int num;
        enum armv4_5_mode mode;
index 168fe127ddb68b960bce21dcd50d9964be835397..c6a46c50ce1ce7f1da46c48a14251ac163201927 100644 (file)
@@ -877,7 +877,7 @@ static int cortex_a8_restore_context(struct target *target)
 
                /* write dirty non-{R0,CPSR} registers sharing the same mode */
                for (i = max - 1, r = cache->reg_list + 1; i > 0; i--, r++) {
-                       struct armv4_5_core_reg *reg;
+                       struct arm_reg *reg;
 
                        if (!r->dirty || i == ARMV4_5_CPSR)
                                continue;
@@ -1018,16 +1018,17 @@ 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 reg *cpsr_r = NULL;
        uint32_t cpsr = 0;
        unsigned cookie = num;
 
@@ -1042,10 +1043,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 = cache->reg_list + 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);
                }
        }
 
@@ -1066,24 +1067,24 @@ 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 reg *cpsr_r = NULL;
        uint32_t cpsr = 0;
        unsigned cookie = num;
 
@@ -1098,10 +1099,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 = cache->reg_list + 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);
                }
        }
 
@@ -1122,15 +1123,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;
 }
 
@@ -1619,7 +1619,6 @@ static void cortex_a8_build_reg_cache(struct target *target)
        armv4_5->core_type = ARM_MODE_MON;
 
        (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
-       armv4_5->core_cache = (*cache_p);
 }
 
 
index f13366ac0b95f331c32d86531b7742b2db0bea71..c908fd709502e1d4dd467886e266cfd3344d293c 100644 (file)
@@ -1646,16 +1646,18 @@ static int xscale_deassert_reset(struct target *target)
        return ERROR_OK;
 }
 
-static int xscale_read_core_reg(struct target *target, int num,
-               enum armv4_5_mode mode)
+static int xscale_read_core_reg(struct target *target, struct reg *r,
+               int num, enum armv4_5_mode mode)
 {
+       /** \todo add debug handler support for core register reads */
        LOG_ERROR("not implemented");
        return ERROR_OK;
 }
 
-static int xscale_write_core_reg(struct target *target, int num,
-               enum armv4_5_mode mode, uint32_t value)
+static int xscale_write_core_reg(struct target *target, struct reg *r,
+               int num, enum armv4_5_mode mode, uint32_t value)
 {
+       /** \todo add debug handler support for core register writes */
        LOG_ERROR("not implemented");
        return ERROR_OK;
 }
@@ -2829,7 +2831,6 @@ static void xscale_build_reg_cache(struct target *target)
        int num_regs = sizeof(xscale_reg_arch_info) / sizeof(struct xscale_reg);
 
        (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
-       armv4_5->core_cache = (*cache_p);
 
        (*cache_p)->next = malloc(sizeof(struct reg_cache));
        cache_p = &(*cache_p)->next;

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)