From ec93209f51afc09e273a4742dc0b5f2cefc15e76 Mon Sep 17 00:00:00 2001
From: David Brownell <dbrownell@users.sourceforge.net>
Date: Tue, 17 Nov 2009 23:50:23 -0800
Subject: ARM: add arm_mode_name()

Add and use arm_mode_name() to map from PSR bits to user
meaningful names.   It uses a new table which, later, can
be used to hold other mode-coupled data.

Add definitions for the "Secure Monitor" mode, as seen on
some ARM11 cores (like ARM1176) and on Cortex-A8.  The
previous mode name scheme didn't understand that mode.

Remove the old mechanism ... there were two copies, caused
by Cortex-A8 needing to add "Secure Monitor" mode support.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
---
 src/target/arm720t.c       |  2 +-
 src/target/arm7_9_common.c | 11 +++++---
 src/target/arm920t.c       |  2 +-
 src/target/arm926ejs.c     |  2 +-
 src/target/armv4_5.c       | 65 +++++++++++++++++++++++++++++++++++++++++-----
 src/target/armv4_5.h       |  4 +--
 src/target/armv7a.c        | 12 +--------
 src/target/armv7a.h        |  2 --
 src/target/xscale.c        |  5 ++--
 9 files changed, 75 insertions(+), 30 deletions(-)

(limited to 'src')

diff --git a/src/target/arm720t.c b/src/target/arm720t.c
index b51f969a..a6c7cc78 100644
--- a/src/target/arm720t.c
+++ b/src/target/arm720t.c
@@ -239,7 +239,7 @@ static int arm720t_arch_state(struct target *target)
 			"MMU: %s, Cache: %s",
 			 armv4_5_state_strings[armv4_5->core_state],
 			 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name ,
-			 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
+			 arm_mode_name(armv4_5->core_mode),
 			 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
 			 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
 			 state[arm720t->armv4_5_mmu.mmu_enabled],
diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c
index b29eb5cc..ff95a0cd 100644
--- a/src/target/arm7_9_common.c
+++ b/src/target/arm7_9_common.c
@@ -1420,7 +1420,8 @@ static int arm7_9_debug_entry(struct target *target)
 		return ERROR_TARGET_FAILURE;
 	}
 
-	LOG_DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]);
+	LOG_DEBUG("target entered debug state in %s mode",
+			 arm_mode_name(armv4_5->core_mode));
 
 	if (armv4_5->core_state == ARMV4_5_STATE_THUMB)
 	{
@@ -1613,7 +1614,8 @@ int arm7_9_restore_context(struct target *target)
 	 */
 	for (i = 0; i < 6; i++)
 	{
-		LOG_DEBUG("examining %s mode", armv4_5_mode_strings[i]);
+		LOG_DEBUG("examining %s mode",
+				arm_mode_name(armv4_5->core_mode));
 		dirty = 0;
 		mode_change = 0;
 		/* check if there are dirty registers in the current mode
@@ -1675,7 +1677,10 @@ int arm7_9_restore_context(struct target *target)
 					num_regs++;
 					reg->dirty = 0;
 					reg->valid = 1;
-					LOG_DEBUG("writing register %i of mode %s with value 0x%8.8" PRIx32 "", j, armv4_5_mode_strings[i], regs[j]);
+					LOG_DEBUG("writing register %i mode %s "
+						"with value 0x%8.8" PRIx32, j,
+						arm_mode_name(armv4_5->core_mode),
+						regs[j]);
 				}
 			}
 
diff --git a/src/target/arm920t.c b/src/target/arm920t.c
index 99b4bbd3..e1dcea7a 100644
--- a/src/target/arm920t.c
+++ b/src/target/arm920t.c
@@ -451,7 +451,7 @@ int arm920t_arch_state(struct target *target)
 			"MMU: %s, D-Cache: %s, I-Cache: %s",
 			 armv4_5_state_strings[armv4_5->core_state],
 			 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name,
-			 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
+			 arm_mode_name(armv4_5->core_mode),
 			 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
 			 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
 			 state[arm920t->armv4_5_mmu.mmu_enabled],
diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c
index cc6318b9..27eb7529 100644
--- a/src/target/arm926ejs.c
+++ b/src/target/arm926ejs.c
@@ -509,7 +509,7 @@ int arm926ejs_arch_state(struct target *target)
 			"MMU: %s, D-Cache: %s, I-Cache: %s",
 			 armv4_5_state_strings[armv4_5->core_state],
 			 Jim_Nvp_value2name_simple(nvp_target_debug_reason,target->debug_reason)->name,
-			 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
+			 arm_mode_name(armv4_5->core_mode),
 			 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
 			 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
 			 state[arm926ejs->armv4_5_mmu.mmu_enabled],
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
index aba44319..6864efbb 100644
--- a/src/target/armv4_5.c
+++ b/src/target/armv4_5.c
@@ -53,13 +53,63 @@ char* armv4_5_core_reg_list[] =
 	"cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und"
 };
 
-static const char *armv4_5_mode_strings_list[] =
-{
-	"Illegal mode value", "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
+static const struct {
+	const char *name;
+	unsigned psr;
+} arm_mode_data[] = {
+	/* Seven modes are standard from ARM7 on. "System" and "User" share
+	 * the same registers; other modes shadow from 3 to 8 registers.
+	 */
+	{
+		.name = "User",
+		.psr = ARMV4_5_MODE_USR,
+	},
+	{
+		.name = "FIQ",
+		.psr = ARMV4_5_MODE_FIQ,
+	},
+	{
+		.name = "Supervisor",
+		.psr = ARMV4_5_MODE_SVC,
+	},
+	{
+		.name = "Abort",
+		.psr = ARMV4_5_MODE_ABT,
+	},
+	{
+		.name = "IRQ",
+		.psr = ARMV4_5_MODE_IRQ,
+	},
+	{
+		.name = "Undefined" /* instruction */,
+		.psr = ARMV4_5_MODE_UND,
+	},
+	{
+		.name = "System",
+		.psr = ARMV4_5_MODE_SYS,
+	},
+	/* TrustZone "Security Extensions" add a secure monitor mode.
+	 * This is distinct from a "debug monitor" which can support
+	 * non-halting debug, in conjunction with some debuggers.
+	 */
+	{
+		.name = "Secure Monitor",
+		.psr = ARM_MODE_MON,
+	},
 };
 
-/* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
-const char **armv4_5_mode_strings = armv4_5_mode_strings_list + 1;
+/** Map PSR mode bits to the name of an ARM processor operating mode. */
+const char *arm_mode_name(unsigned psr_mode)
+{
+	unsigned i;
+
+	for (i = 0; i < ARRAY_SIZE(arm_mode_data); i++) {
+		if (arm_mode_data[i].psr == psr_mode)
+			return arm_mode_data[i].name;
+	}
+	LOG_ERROR("unrecognized psr mode: %#02x", psr_mode);
+	return "UNRECOGNIZED";
+}
 
 /** Map PSR mode bits to linear number */
 int armv4_5_mode_to_number(enum armv4_5_mode mode)
@@ -282,7 +332,8 @@ int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
 
 		if (armv4_5_target->core_mode != (enum armv4_5_mode)(value & 0x1f))
 		{
-			LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings[armv4_5_mode_to_number(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);
 		}
@@ -357,7 +408,7 @@ int armv4_5_arch_state(struct target *target)
 	LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "",
 			 armv4_5_state_strings[armv4_5->core_state],
 			 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name,
-			 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
+			 arm_mode_name(armv4_5->core_mode),
 			 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
 			 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
 
diff --git a/src/target/armv4_5.h b/src/target/armv4_5.h
index d126f964..5b7a5220 100644
--- a/src/target/armv4_5.h
+++ b/src/target/armv4_5.h
@@ -35,16 +35,16 @@ typedef enum armv4_5_mode
 	ARMV4_5_MODE_IRQ = 18,
 	ARMV4_5_MODE_SVC = 19,
 	ARMV4_5_MODE_ABT = 23,
+	ARM_MODE_MON = 26,
 	ARMV4_5_MODE_UND = 27,
 	ARMV4_5_MODE_SYS = 31,
 	ARMV4_5_MODE_ANY = -1
 } armv4_5_mode_t;
 
+const char *arm_mode_name(unsigned psr_mode);
 int armv4_5_mode_to_number(enum armv4_5_mode mode);
 enum armv4_5_mode armv4_5_number_to_mode(int number);
 
-extern const char **armv4_5_mode_strings;
-
 typedef enum armv4_5_state
 {
 	ARMV4_5_STATE_ARM,
diff --git a/src/target/armv7a.c b/src/target/armv7a.c
index 1518674a..e13b33b4 100644
--- a/src/target/armv7a.c
+++ b/src/target/armv7a.c
@@ -47,15 +47,6 @@ char* armv7a_core_reg_list[] =
 	"r13_mon", "lr_mon", "spsr_mon"
 };
 
-char * armv7a_mode_strings_list[] =
-{
-	"Illegal mode value", "User", "FIQ", "IRQ",
-	"Supervisor", "Abort", "Undefined", "System", "Monitor"
-};
-
-/* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
-char** armv7a_mode_strings = armv7a_mode_strings_list+1;
-
 char* armv7a_state_strings[] =
 {
 	"ARM", "Thumb", "Jazelle", "ThumbEE"
@@ -183,8 +174,7 @@ int armv7a_arch_state(struct target *target)
 		 armv7a_state_strings[armv7a->core_state],
 		 Jim_Nvp_value2name_simple(nvp_target_debug_reason,
 				target->debug_reason)->name,
-		 armv7a_mode_strings[
-			armv7a_mode_to_number(armv4_5->core_mode)],
+		 arm_mode_name(armv4_5->core_mode),
 		 armv7a_core_reg_list[armv7a_core_reg_map[
 			armv7a_mode_to_number(armv4_5->core_mode)][16]],
 		 buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
diff --git a/src/target/armv7a.h b/src/target/armv7a.h
index 4d29ef9b..e781e720 100644
--- a/src/target/armv7a.h
+++ b/src/target/armv7a.h
@@ -37,8 +37,6 @@ typedef enum armv7a_mode
 	ARMV7A_MODE_ANY = -1
 } armv7a_t;
 
-extern char **armv7a_mode_strings;
-
 typedef enum armv7a_state
 {
 	ARMV7A_STATE_ARM,
diff --git a/src/target/xscale.c b/src/target/xscale.c
index a4a8eabd..38928f41 100644
--- a/src/target/xscale.c
+++ b/src/target/xscale.c
@@ -857,7 +857,7 @@ static int xscale_arch_state(struct target *target)
 			"%s",
 			 armv4_5_state_strings[armv4_5->core_state],
 			 Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name ,
-			 armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
+			 arm_mode_name(armv4_5->core_mode),
 			 buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32),
 			 buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
 			 state[xscale->armv4_5_mmu.mmu_enabled],
@@ -960,7 +960,8 @@ static int xscale_debug_entry(struct target *target)
 		LOG_ERROR("cpsr contains invalid mode value - communication failure");
 		return ERROR_TARGET_FAILURE;
 	}
-	LOG_DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]);
+	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;
-- 
cgit v1.2.3