summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/target/arm.h17
-rw-r--r--src/target/armv4_5.c6
-rw-r--r--src/target/armv7m.c17
-rw-r--r--src/target/armv7m.h4
-rw-r--r--src/target/cortex_m3.c39
5 files changed, 74 insertions, 9 deletions
diff --git a/src/target/arm.h b/src/target/arm.h
index 988266e3..c72b1942 100644
--- a/src/target/arm.h
+++ b/src/target/arm.h
@@ -40,9 +40,17 @@
*/
/**
- * These numbers match the five low bits of the *PSR registers on
+ * Represent state of an ARM core.
+ *
+ * Most numbers match the five low bits of the *PSR registers on
* "classic ARM" processors, which build on the ARMv4 processor
* modes and register set.
+ *
+ * ARM_MODE_ANY is a magic value, often used as a wildcard.
+ *
+ * Only the microcontroller cores (ARMv6-M, ARMv7-M) support ARM_MODE_THREAD,
+ * ARM_MODE_USER_THREAD, and ARM_MODE_HANDLER. Those are the only modes
+ * they support.
*/
enum arm_mode {
ARM_MODE_USR = 16,
@@ -53,6 +61,11 @@ enum arm_mode {
ARM_MODE_MON = 26,
ARM_MODE_UND = 27,
ARM_MODE_SYS = 31,
+
+ ARM_MODE_THREAD,
+ ARM_MODE_USER_THREAD,
+ ARM_MODE_HANDLER,
+
ARM_MODE_ANY = -1
};
@@ -96,6 +109,8 @@ struct arm {
* ARM_MODE_ANY indicates the standard set of 37 registers,
* seen on for example ARM7TDMI cores. ARM_MODE_MON indicates three
* more registers are shadowed, for "Secure Monitor" mode.
+ * ARM_MODE_THREAD indicates a microcontroller profile core,
+ * which only shadows SP.
*/
enum arm_mode core_type;
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
index c7b73676..8d3a8917 100644
--- a/src/target/armv4_5.c
+++ b/src/target/armv4_5.c
@@ -1426,10 +1426,12 @@ int arm_init_arch_info(struct target *target, struct arm *armv4_5)
armv4_5->target = target;
armv4_5->common_magic = ARM_COMMON_MAGIC;
- arm_set_cpsr(armv4_5, ARM_MODE_USR);
/* core_type may be overridden by subtype logic */
- armv4_5->core_type = ARM_MODE_ANY;
+ if (armv4_5->core_type != ARM_MODE_THREAD) {
+ armv4_5->core_type = ARM_MODE_ANY;
+ arm_set_cpsr(armv4_5, ARM_MODE_USR);
+ }
/* default full_context() has no core-specific optimizations */
if (!armv4_5->full_context && armv4_5->read_core_reg)
diff --git a/src/target/armv7m.c b/src/target/armv7m.c
index 9fe705af..faa886b4 100644
--- a/src/target/armv7m.c
+++ b/src/target/armv7m.c
@@ -473,6 +473,7 @@ int armv7m_run_algorithm(struct target *target,
int armv7m_arch_state(struct target *target)
{
struct armv7m_common *armv7m = target_to_armv7m(target);
+ struct arm *arm = &armv7m->arm;
uint32_t ctrl, sp;
ctrl = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32);
@@ -483,7 +484,7 @@ int armv7m_arch_state(struct target *target)
debug_reason_name(target),
armv7m_mode_strings[armv7m->core_mode],
armv7m_exception_string(armv7m->exception_number),
- buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32),
+ buf_get_u32(arm->cpsr->value, 0, 32),
buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_PC].value, 0, 32),
(ctrl & 0x02) ? 'p' : 'm',
sp);
@@ -499,6 +500,7 @@ static const struct reg_arch_type armv7m_reg_type = {
struct reg_cache *armv7m_build_reg_cache(struct target *target)
{
struct armv7m_common *armv7m = target_to_armv7m(target);
+ struct arm *arm = &armv7m->arm;
int num_regs = ARMV7M_NUM_REGS;
struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
struct reg_cache *cache = malloc(sizeof(struct reg_cache));
@@ -532,19 +534,28 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target)
reg_list[i].arch_info = &arch_info[i];
}
+ arm->cpsr = reg_list + ARMV7M_xPSR;
+ arm->core_cache = cache;
return cache;
}
/** Sets up target as a generic ARMv7-M core */
int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m)
{
+ struct arm *arm = &armv7m->arm;
+
armv7m->common_magic = ARMV7M_COMMON_MAGIC;
- target->arch_info = armv7m;
+ arm->core_type = ARM_MODE_THREAD;
+ arm->arch_info = armv7m;
+
+ /* FIXME remove v7m-specific r/w core_reg functions;
+ * use the generic ARM core support..
+ */
armv7m->read_core_reg = armv7m_read_core_reg;
armv7m->write_core_reg = armv7m_write_core_reg;
- return ERROR_OK;
+ return arm_init_arch_info(target, arm);
}
/** Generates a CRC32 checksum of a memory region. */
diff --git a/src/target/armv7m.h b/src/target/armv7m.h
index b6be1d22..89c5064c 100644
--- a/src/target/armv7m.h
+++ b/src/target/armv7m.h
@@ -100,6 +100,8 @@ enum
struct armv7m_common
{
+ struct arm arm;
+
int common_magic;
struct reg_cache *core_cache;
enum armv7m_mode core_mode;
@@ -128,7 +130,7 @@ struct armv7m_common
static inline struct armv7m_common *
target_to_armv7m(struct target *target)
{
- return target->arch_info;
+ return container_of(target->arch_info, struct armv7m_common, arm);
}
static inline bool is_armv7m(struct armv7m_common *armv7m)
diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c
index 3f347697..fbc879f1 100644
--- a/src/target/cortex_m3.c
+++ b/src/target/cortex_m3.c
@@ -323,6 +323,24 @@ static int cortex_m3_examine_exception_reason(struct target *target)
return ERROR_OK;
}
+/* PSP is used in some thread modes */
+static const int armv7m_psp_reg_map[17] = {
+ ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
+ ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
+ ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
+ ARMV7M_R12, ARMV7M_PSP, ARMV7M_R14, ARMV7M_PC,
+ ARMV7M_xPSR,
+};
+
+/* MSP is used in handler and some thread modes */
+static const int armv7m_msp_reg_map[17] = {
+ ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
+ ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
+ ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
+ ARMV7M_R12, ARMV7M_MSP, ARMV7M_R14, ARMV7M_PC,
+ ARMV7M_xPSR,
+};
+
static int cortex_m3_debug_entry(struct target *target)
{
int i;
@@ -330,6 +348,7 @@ static int cortex_m3_debug_entry(struct target *target)
int retval;
struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
struct armv7m_common *armv7m = &cortex_m3->armv7m;
+ struct arm *arm = &armv7m->arm;
struct swjdp_common *swjdp = &armv7m->swjdp_info;
struct reg *r;
@@ -377,11 +396,27 @@ static int cortex_m3_debug_entry(struct target *target)
{
armv7m->core_mode = ARMV7M_MODE_HANDLER;
armv7m->exception_number = (xPSR & 0x1FF);
+
+ arm->core_mode = ARM_MODE_HANDLER;
+ arm->map = armv7m_msp_reg_map;
}
else
{
- armv7m->core_mode = buf_get_u32(armv7m->core_cache
- ->reg_list[ARMV7M_CONTROL].value, 0, 1);
+ unsigned control = buf_get_u32(armv7m->core_cache
+ ->reg_list[ARMV7M_CONTROL].value, 0, 2);
+
+ /* is this thread privileged? */
+ armv7m->core_mode = control & 1;
+ arm->core_mode = armv7m->core_mode
+ ? ARM_MODE_USER_THREAD
+ : ARM_MODE_THREAD;
+
+ /* which stack is it using? */
+ if (control & 2)
+ arm->map = armv7m_psp_reg_map;
+ else
+ arm->map = armv7m_msp_reg_map;
+
armv7m->exception_number = 0;
}