From 195ce5eb273983dbeabeea41cc18b77e4f30ab41 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 19 Nov 2009 02:33:01 -0800 Subject: [PATCH] ARMv7-A: use standard ARM core states We don't want an ARMv7-specific core state enumeration just to add ThumbEE state. Update the generic stuff to handle that, and replace the V7-specific bits with it. For Cortex-A8: on debug entry, check both the T and J bits instead of just the T bit. When the J bit is set, set the right state and warn appropriately. (And while we're at it, move the generic arm struct to the front of the v7a structure, for somewhat better code generation.) Signed-off-by: David Brownell --- src/target/armv4_5.c | 2 +- src/target/armv4_5.h | 1 + src/target/armv7a.c | 7 +----- src/target/armv7a.h | 14 ++---------- src/target/cortex_a8.c | 50 ++++++++++++++++++++++++++++++++---------- 5 files changed, 43 insertions(+), 31 deletions(-) diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 6c6f2bfe..5e882e67 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -227,7 +227,7 @@ enum armv4_5_mode armv4_5_number_to_mode(int number) char* armv4_5_state_strings[] = { - "ARM", "Thumb", "Jazelle" + "ARM", "Thumb", "Jazelle", "ThumbEE", }; static const struct armv4_5_core_reg armv4_5_core_reg_list_arch_info[] = diff --git a/src/target/armv4_5.h b/src/target/armv4_5.h index e3d053c9..6b1dd769 100644 --- a/src/target/armv4_5.h +++ b/src/target/armv4_5.h @@ -52,6 +52,7 @@ typedef enum armv4_5_state ARMV4_5_STATE_ARM, ARMV4_5_STATE_THUMB, ARMV4_5_STATE_JAZELLE, + ARM_STATE_THUMB_EE, } armv4_5_state_t; extern char* armv4_5_state_strings[]; diff --git a/src/target/armv7a.c b/src/target/armv7a.c index 98e3fa3f..ea883c16 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -34,11 +34,6 @@ #include -static const char *armv7a_state_strings[] = -{ - "ARM", "Thumb", "Jazelle", "ThumbEE" -}; - static void armv7a_show_fault_registers(struct target *target) { uint32_t dfsr, ifsr, dfar, ifar; @@ -75,7 +70,7 @@ int armv7a_arch_state(struct target *target) LOG_USER("target halted in %s state due to %s, current mode: %s\n" "cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n" "MMU: %s, D-Cache: %s, I-Cache: %s", - armv7a_state_strings[armv7a->core_state], + armv4_5_state_strings[armv4_5->core_state], Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name, arm_mode_name(armv4_5->core_mode), diff --git a/src/target/armv7a.h b/src/target/armv7a.h index f31a7af8..635cd40e 100644 --- a/src/target/armv7a.h +++ b/src/target/armv7a.h @@ -24,15 +24,6 @@ #include "armv4_5_mmu.h" #include "armv4_5_cache.h" - -typedef enum armv7a_state -{ - ARMV7A_STATE_ARM, - ARMV7A_STATE_THUMB, - ARMV7A_STATE_JAZELLE, - ARMV7A_STATE_THUMBEE, -} armv7a_state_t; - enum { ARM_PC = 15, @@ -64,9 +55,9 @@ enum struct armv7a_common { + struct arm armv4_5_common; int common_magic; struct reg_cache *core_cache; - enum armv7a_state core_state; /* arm adp debug port */ struct swjdp_common swjdp_info; @@ -78,7 +69,6 @@ struct armv7a_common /* Cache and Memory Management Unit */ struct armv4_5_mmu_common armv4_5_mmu; - struct arm armv4_5_common; int (*read_cp15)(struct target *target, uint32_t op1, uint32_t op2, @@ -107,7 +97,7 @@ struct armv7a_algorithm int common_magic; enum armv4_5_mode core_mode; - enum armv7a_state core_state; + enum armv4_5_state core_state; }; struct armv7a_core_reg diff --git a/src/target/cortex_a8.c b/src/target/cortex_a8.c index fc788446..d62740c2 100644 --- a/src/target/cortex_a8.c +++ b/src/target/cortex_a8.c @@ -491,16 +491,21 @@ static int cortex_a8_resume(struct target *target, int current, /* Make sure that the Armv7 gdb thumb fixups does not * kill the return address */ - if (armv7a->core_state == ARMV7A_STATE_ARM) + switch (armv4_5->core_state) { + case ARMV4_5_STATE_ARM: resume_pc &= 0xFFFFFFFC; - } - /* When the return address is loaded into PC - * bit 0 must be 1 to stay in Thumb state - */ - if (armv7a->core_state == ARMV7A_STATE_THUMB) - { + break; + case ARMV4_5_STATE_THUMB: + case ARM_STATE_THUMB_EE: + /* When the return address is loaded into PC + * bit 0 must be 1 to stay in Thumb state + */ resume_pc |= 0x1; + break; + case ARMV4_5_STATE_JAZELLE: + LOG_ERROR("How do I resume into Jazelle state??"); + return ERROR_FAIL; } LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc); buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, @@ -630,9 +635,29 @@ static int cortex_a8_debug_entry(struct target *target) LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr); armv4_5->core_mode = cpsr & 0x1F; - armv7a->core_state = (cpsr & 0x20) - ? ARMV7A_STATE_THUMB - : ARMV7A_STATE_ARM; + + 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 */ reg = armv4_5->core_cache->reg_list + ARMV4_5_CPSR; @@ -651,7 +676,7 @@ static int cortex_a8_debug_entry(struct target *target) } /* Fixup PC Resume Address */ - if (armv7a->core_state == ARMV7A_STATE_THUMB) + if (cpsr & (1 << 5)) { // T bit set for Thumb or ThumbEE state regfile[ARM_PC] -= 4; @@ -775,7 +800,8 @@ static int cortex_a8_step(struct target *target, int current, uint32_t address, /* Setup single step breakpoint */ stepbreakpoint.address = address; - stepbreakpoint.length = (armv7a->core_state == ARMV7A_STATE_THUMB) ? 2 : 4; + stepbreakpoint.length = (armv4_5->core_state == ARMV4_5_STATE_THUMB) + ? 2 : 4; stepbreakpoint.type = BKPT_HARD; stepbreakpoint.set = 0; -- 2.39.5